Vize

コンポーネントと props のルール

このルール群では、コンポーネントの名前・登録・使い方と、props の変更や未使用の宣言を確認します。 コンポーネントを追加したり、親子間で渡すデータや動的コンポーネントの切り替えを変更したりするときに確認してください。

たとえば、props を直接変更しない例では、親から受け取った値を書き換える代わりに、更新をイベントで親へ通知する形を比較できます。 掲載された設定でルールを有効にし、vp run lint を実行してください。 Vue の全ルールでは、テンプレートや SFC の関連ルールも確認できます。

このページに、各ルールの目的・前提・設定と、省略のない悪い例・良い例をまとめています。変更箇所は行の色で示します。コードをコピーすると、ソースコード全体を取得できます。各例に現在の対応範囲も明記しています。

ルール 例 目的
vue/component-definition-name-casing 悪い · 良い コンポーネント定義名を PascalCase または kebab-case に揃えます。
vue/component-name-in-template-casing 悪い · 良い テンプレート内のコンポーネント名を指定した形式に揃えます。
vue/multi-word-component-names 悪い · 良い コンポーネント名を複数の単語で構成します。
vue/no-mutating-props 悪い · 良い 親から受け取った prop を子コンポーネントで変更する箇所を検出します。
vue/no-non-component-keep-alive-child 悪い · 良い KeepAlive の直下に通常の HTML 要素を置く箇所を検出します。
vue/no-reserved-component-names 悪い · 良い 予約済みのコンポーネント名を検出します。
vue/no-unused-components 悪い · 良い 登録しているのにテンプレートで使わないコンポーネントを検出します。
vue/no-unused-properties 悪い · 良い defineProps に宣言しているのに使わない prop を検出します。
vue/require-component-is 悪い · 良い 動的 component 要素に :is を指定します。
vue/require-component-registration 悪い · 良い 使用するコンポーネントを import または登録します。

全ルール · ルールのオプション · ESLint 移行対応表 · プロジェクトの検査 · 子への属性の継承

vue/component-definition-name-casing

コンポーネント定義名を PascalCase または kebab-case に揃えます。

悪い例 · 良い例

既定の重大度: warning
プリセット: happy-path, nuxt, ecosystem, opinionated
自動修正: なし。修正内容を確認してください
適用範囲: Vue SFC のテンプレートと各ブロック。ルールに必要な script の文脈も例に含めています。
オプション: ルール固有のオプションはありません。重大度とプリセットは設定できます。

対象はファイル名です。PascalCase と kebab-case は許可され、混在する形式は検出されます。

設定(Vite+)

import { defineConfig } from "@vizejs/vite-plugin/vite-plus";

export default defineConfig({
  vue: {
    linter: {
      "preset": "incremental",
      "rules": {
        "vue/component-definition-name-casing": "warn"
      }
    },
  },
});
vp run lint

悪い

ファイル名 myComponent.vue が先頭の小文字と途中の大文字を混在させ、PascalCase / kebab-case のどちらにもなっていません。

myComponent.vue

<template><p>Content</p></template>

良い

ファイル名を PascalCase の MyComponent.vue に変更します。テンプレートの内容は同じです。

MyComponent.vue

<template><p>Content</p></template>

良い例は上記の設定でこのルールの診断が出ない例です。他のルールの診断は出る場合があります。

実装 · 全ルール

vue/component-name-in-template-casing

テンプレート内のコンポーネント名を指定した形式に揃えます。

悪い例 · 良い例

既定の重大度: warning
プリセット: nuxt, opinionated
自動修正: 対応している診断で利用できます
適用範囲: Vue SFC のテンプレートと各ブロック。ルールに必要な script の文脈も例に含めています。
オプション: 型付きオプションと既定値を参照してください。

設定(Vite+)

import { defineConfig } from "@vizejs/vite-plugin/vite-plus";

export default defineConfig({
  vue: {
    linter: {
      "preset": "incremental",
      "rules": {
        "vue/component-name-in-template-casing": "warn"
      }
    },
  },
});
vp run lint

悪い

PascalCase の方針に対し、コンポーネントを kebab-case と camelCase で記述しています。

<script setup>
import MyComponent from "./MyComponent.vue";
</script>
<template>
  <my-component />
  <myComponent />
</template>

良い

MyComponent を PascalCase で記述します。標準の slot は小文字のままです。

<script setup>
import MyComponent from "./MyComponent.vue";
</script>
<template>
  <MyComponent />
  <RouterView />
  <slot />
</template>

良い例は上記の設定でこのルールの診断が出ない例です。他のルールの診断は出る場合があります。

実装 · 全ルール

vue/multi-word-component-names

コンポーネント名を複数の単語で構成します。

悪い例 · 良い例

既定の重大度: error
プリセット: essential, nuxt, opinionated
自動修正: なし。修正内容を確認してください
適用範囲: Vue SFC のテンプレートと各ブロック。ルールに必要な script の文脈も例に含めています。
オプション: ルール固有のオプションはありません。重大度とプリセットは設定できます。

検出対象はファイル名です。同じコンポーネントのファイル名を変更します。子要素のタグ名は対象ではありません。

設定(Vite+)

import { defineConfig } from "@vizejs/vite-plugin/vite-plus";

export default defineConfig({
  vue: {
    linter: {
      "preset": "incremental",
      "rules": {
        "vue/multi-word-component-names": "error"
      }
    },
  },
});
vp run lint

悪い

Item.vue は一つの語だけのコンポーネント名です。

Item.vue

<template><p>Item</p></template>

良い

同じコンポーネントのファイル名を、複数の単語からなる TodoItem.vue に変更します。

TodoItem.vue

<template><p>Item</p></template>

良い例は上記の設定でこのルールの診断が出ない例です。他のルールの診断は出る場合があります。

実装 · 全ルール

vue/no-mutating-props

親から受け取った prop を子コンポーネントで変更する箇所を検出します。

悪い例 · 良い例

既定の重大度: error
プリセット: essential, happy-path, nuxt, ecosystem, opinionated
自動修正: なし。修正内容を確認してください
適用範囲: Vue SFC のテンプレートと各ブロック。ルールに必要な script の文脈も例に含めています。
オプション: 型付きオプションと既定値を参照してください。

設定(Vite+)

import { defineConfig } from "@vizejs/vite-plugin/vite-plus";

export default defineConfig({
  vue: {
    linter: {
      "preset": "incremental",
      "rules": {
        "vue/no-mutating-props": "error"
      }
    },
  },
});
vp run lint

悪い

props.count の加算で、親から受け取った値を直接変更しています。

<script setup lang="ts">
const props = defineProps<{ count: number }>();

props.count++;
</script>

良い

次の値を update:count で通知し、prop の変更は親が行う形にします。

<script setup lang="ts">
const props = defineProps<{ count: number }>();
const emit = defineEmits<{ "update:count": [value: number] }>();

function increment() {
  emit("update:count", props.count + 1);
}
</script>

良い例は上記の設定でこのルールの診断が出ない例です。他のルールの診断は出る場合があります。

実装 · 全ルール

vue/no-non-component-keep-alive-child

KeepAlive の直下に通常の HTML 要素を置く箇所を検出します。

悪い例 · 良い例

既定の重大度: warning
プリセット: essential, happy-path, nuxt, ecosystem, opinionated
自動修正: なし。修正内容を確認してください
適用範囲: Vue SFC のテンプレートと各ブロック。ルールに必要な script の文脈も例に含めています。
オプション: ルール固有のオプションはありません。重大度とプリセットは設定できます。

設定(Vite+)

import { defineConfig } from "@vizejs/vite-plugin/vite-plus";

export default defineConfig({
  vue: {
    linter: {
      "preset": "incremental",
      "rules": {
        "vue/no-non-component-keep-alive-child": "warn"
      }
    },
  },
});
vp run lint

悪い

KeepAlive の条件付きの子が UserCard ではなく、標準の div になっています。

<template>
  <KeepAlive>
    <div v-if="ready">
      <UserCard />
    </div>
  </KeepAlive>
</template>

良い

最初の例は UserCard を条件付きの子にします。v-show のラッパー要素はこの条件付きの子の検査の対象外を示す例で、標準要素がキャッシュされるという意味ではありません。

<template>
  <KeepAlive>
    <UserCard v-if="ready" />
  </KeepAlive>
  <KeepAlive>
    <div v-show="opened">
      <UserCard />
    </div>
  </KeepAlive>
</template>

良い例は上記の設定でこのルールの診断が出ない例です。他のルールの診断は出る場合があります。

実装 · 全ルール

vue/no-reserved-component-names

予約済みのコンポーネント名を検出します。

悪い例 · 良い例

既定の重大度: error
プリセット: essential, happy-path, nuxt, ecosystem, opinionated
自動修正: なし。修正内容を確認してください
適用範囲: Vue SFC のテンプレートと各ブロック。ルールに必要な script の文脈も例に含めています。
オプション: ルール固有のオプションはありません。重大度とプリセットは設定できます。

設定(Vite+)

import { defineConfig } from "@vizejs/vite-plugin/vite-plus";

export default defineConfig({
  vue: {
    linter: {
      "preset": "incremental",
      "rules": {
        "vue/no-reserved-component-names": "error"
      }
    },
  },
});
vp run lint

悪い

コンポーネント名の button が、標準の HTML 要素名と競合しています。

<script>
export default {
  name: "button",
};
</script>

良い

標準の button と重複しない、アプリのコンポーネント名 AppButton を指定します。

<script setup lang="ts">
defineOptions({ name: "AppButton" });
</script>

<template>
  <Transition>
    <AppButton />
  </Transition>
</template>

良い例は上記の設定でこのルールの診断が出ない例です。他のルールの診断は出る場合があります。

実装 · 全ルール

vue/no-unused-components

登録しているのにテンプレートで使わないコンポーネントを検出します。

悪い例 · 良い例

既定の重大度: warning
プリセット: essential, happy-path, nuxt, ecosystem, opinionated
自動修正: なし。修正内容を確認してください
適用範囲: Vue SFC のテンプレートと各ブロック。ルールに必要な script の文脈も例に含めています。
オプション: ルール固有のオプションはありません。重大度とプリセットは設定できます。

設定(Vite+)

import { defineConfig } from "@vizejs/vite-plugin/vite-plus";

export default defineConfig({
  vue: {
    linter: {
      "preset": "incremental",
      "rules": {
        "vue/no-unused-components": "warn"
      }
    },
  },
});
vp run lint

悪い

UserAvatar をコンポーネントとして import していますが、テンプレートで使っていません。

<script setup lang="ts">
import UserAvatar from "./UserAvatar.vue";
</script>

<template>
  <p>{{ user.name }}</p>
</template>

良い

import した UserAvatar をテンプレートで表示し、user を渡します。

<script setup lang="ts">
import UserAvatar from "./UserAvatar.vue";
</script>

<template>
  <UserAvatar :user="user" />
</template>

良い例は上記の設定でこのルールの診断が出ない例です。他のルールの診断は出る場合があります。

実装 · 全ルール

vue/no-unused-properties

defineProps に宣言しているのに使わない prop を検出します。

悪い例 · 良い例

既定の重大度: warning
プリセット: happy-path, nuxt, ecosystem, opinionated
自動修正: なし。修正内容を確認してください
適用範囲: Vue SFC のテンプレートと各ブロック。ルールに必要な script の文脈も例に含めています。
オプション: ルール固有のオプションはありません。重大度とプリセットは設定できます。

設定(Vite+)

import { defineConfig } from "@vizejs/vite-plugin/vite-plus";

export default defineConfig({
  vue: {
    linter: {
      "preset": "incremental",
      "rules": {
        "vue/no-unused-properties": "warn"
      }
    },
  },
});
vp run lint

悪い

description の prop を宣言していますが、表示には title しか使っていません。

<script setup lang="ts">
defineProps<{ title: string; description: string }>();
</script>

<template>
  <h1>{{ title }}</h1>
</template>

良い

宣言した両方の prop をテンプレートで参照します。

<script setup lang="ts">
defineProps<{ title: string; description: string }>();
</script>

<template>
  <h1>{{ title }}</h1>
  <p>{{ description }}</p>
</template>

良い例は上記の設定でこのルールの診断が出ない例です。他のルールの診断は出る場合があります。

実装 · 全ルール

vue/require-component-is

動的 component 要素に :is を指定します。

悪い例 · 良い例

既定の重大度: error
プリセット: essential, happy-path, nuxt, ecosystem, opinionated
自動修正: なし。修正内容を確認してください
適用範囲: Vue SFC のテンプレートと各ブロック。ルールに必要な script の文脈も例に含めています。
オプション: ルール固有のオプションはありません。重大度とプリセットは設定できます。

設定(Vite+)

import { defineConfig } from "@vizejs/vite-plugin/vite-plus";

export default defineConfig({
  vue: {
    linter: {
      "preset": "incremental",
      "rules": {
        "vue/require-component-is": "error"
      }
    },
  },
});
vp run lint

悪い

動的な <component> に is がなく、描画するコンポーネントを選べません。

<template>
  <component />
</template>

良い

:is="currentComponent" で描画対象を指定します。対象は実行時に変更できます。

<template>
  <component :is="currentComponent" />
</template>

良い例は上記の設定でこのルールの診断が出ない例です。他のルールの診断は出る場合があります。

実装 · 全ルール

vue/require-component-registration

使用するコンポーネントを import または登録します。

悪い例 · 良い例

既定の重大度: warning
プリセット: opinionated
自動修正: なし。修正内容を確認してください
適用範囲: Vue SFC のテンプレートと各ブロック。ルールに必要な script の文脈も例に含めています。
オプション: 型付きオプションと既定値を参照してください。

アプリケーションのプラグインや Musea の previewSetup が登録するコンポーネント名を明示します。PascalCase と kebab-case を許可し、正規表現は解釈しません。オプションだけではルールは有効になりません。後の設定は一覧全体を置き換え、空の一覧は継承した名前を消します。

設定(Vite+)

import { defineConfig } from "@vizejs/vite-plugin/vite-plus";

export default defineConfig({
  vue: {
    linter: {
      "preset": "incremental",
      "rules": {
        "vue/require-component-registration": "warn"
      },
      "ruleOptions": {
        "vue/require-component-registration": {
          "globals": [
            "MyButton",
            "MyIcon"
          ]
        }
      }
    },
  },
});
vp run lint

悪い

MissingWidget は登録されておらず、設定したグローバルコンポーネント一覧にもありません。

<template>
<MissingWidget />
</template>

良い

MyButton は例の globals に含まれます。既知のグローバルコンポーネントを検査対象から除く設定で、import や登録そのものは行いません。

<template>
<MyButton />
</template>

良い例は上記の設定でこのルールの診断が出ない例です。他のルールの診断は出る場合があります。

実装 · 全ルール