Vize

Vue ルール

すべての Vue ルールの目的・設定・悪い例・良い例をこのページにまとめています。変更箇所は行の色で示します。コードをコピーすると、省略のないソースコード全体を取得できます。

ルール 例 目的
vue/a11y-img-alt 悪い · 良い 画像に代替テキストの alt 属性を指定します。
vue/attribute-hyphenation 悪い · 良い コンポーネントの prop 属性名を設定した形式に揃えます。
vue/attribute-order 悪い · 良い テンプレートの属性を一定の順に並べます。
vue/component-definition-name-casing 悪い · 良い コンポーネント定義名を PascalCase または kebab-case に揃えます。
vue/component-name-in-template-casing 悪い · 良い テンプレート内のコンポーネント名を指定した形式に揃えます。
vue/html-button-has-type 悪い · 良い button に有効な type を明示します。
vue/html-quotes 悪い · 良い HTML 属性値の引用符を揃えます。
vue/html-self-closing 悪い · 良い 要素の種類ごとに自己終了タグの形式を揃えます。
vue/max-template-complexity 悪い · 良い コンポーネント自身のテンプレートの複雑度を制限します。
vue/multi-word-component-names 悪い · 良い コンポーネント名を複数の単語で構成します。
vue/mustache-interpolation-spacing 悪い · 良い mustache 内の空白を揃えます。
vue/no-array-index-key 悪い · 良い v-for の配列インデックスをそのまま key に使う箇所を検出します。
vue/no-bare-strings-in-template 悪い · 良い テンプレートに直接書かれた、国際化の対象となるテキストを検出します。
vue/no-boolean-attr-value 悪い · 良い HTML の真偽属性に不要な値を指定した箇所を検出します。
vue/no-child-content 悪い · 良い v-html / v-text と子コンテンツを同時に指定する箇所を検出します。
vue/no-deprecated-filter 悪い · 良い Vue 2 のパイプによるフィルター構文を検出します。
vue/no-deprecated-functional-template 悪い · 良い SFC の template で削除済みの functional 属性を検出します。
vue/no-deprecated-html-element-is 悪い · 良い 通常の HTML 要素で旧形式の is を使う箇所を検出します。
vue/no-deprecated-inline-template 悪い · 良い 削除済みの inline-template 属性を検出します。
vue/no-deprecated-router-link-tag-prop 悪い · 良い router-link の削除済み tag prop を検出します。
vue/no-deprecated-scope-attribute 悪い · 良い template の削除済み scope 属性を検出します。
vue/no-deprecated-slot-attribute 悪い · 良い 削除済みの slot 属性を検出します。
vue/no-deprecated-slot-scope-attribute 悪い · 良い 削除済みの slot-scope 属性を検出します。
vue/no-deprecated-v-bind-sync 悪い · 良い 削除済みの v-bind の .sync 修飾子を検出します。
vue/no-deprecated-v-is 悪い · 良い 非推奨の v-is ディレクティブを検出します。
vue/no-deprecated-v-on-native-modifier 悪い · 良い 削除済みの v-on の .native 修飾子を検出します。
vue/no-deprecated-v-on-number-modifiers 悪い · 良い v-on の削除済みの数値 keyCode 修飾子を検出します。
vue/no-dupe-v-else-if 悪い · 良い v-if / v-else-if の条件重複を検出します。
vue/no-duplicate-attributes 悪い · 良い 同じ要素の属性重複を検出します。
vue/no-empty-component-block 悪い · 良い 空の SFC ブロックを検出します。
vue/no-inline-style 悪い · 良い インラインの style 属性を検出します。
vue/no-invalid-html-attribute 悪い · 良い 静的 HTML 属性の無効な値を検出します。現在は rel が対象です。
vue/no-lone-template 悪い · 良い 不要な template 要素を検出します。
vue/no-multi-spaces 悪い · 良い 連続する不要な空白を検出します。
vue/no-multiple-objects-in-class 悪い · 良い :class 配列内の複数のオブジェクト指定をまとめます。
vue/no-multiple-template-root 悪い · 良い 単一ルートを要求するテンプレートで複数ルートを検出します。
vue/no-mutating-props 悪い · 良い 親から受け取った prop を子コンポーネントで変更する箇所を検出します。
vue/no-negated-v-if-condition 悪い · 良い v-else がある条件分岐の否定条件を反転して読みやすくします。
vue/no-non-component-keep-alive-child 悪い · 良い KeepAlive の直下に通常の HTML 要素を置く箇所を検出します。
vue/no-preprocessor-lang 悪い · 良い CSS プリプロセッサーより標準の CSS を使う方針を示します。
vue/no-reserved-component-names 悪い · 良い 予約済みのコンポーネント名を検出します。
vue/no-root-v-if 悪い · 良い テンプレートの単一ルートに v-if を指定する箇所を検出します。
vue/no-script-non-standard-lang 悪い · 良い script の非標準の lang 指定を避ける方針を示します。
vue/no-src-attribute 悪い · 良い SFC ブロックの外部 src 指定を検出します。
vue/no-static-inline-styles 悪い · 良い 静的なインライン style 属性を検出します。
vue/no-template-key 悪い · 良い v-for 用ではない template の key 指定を検出します。
vue/no-template-lang 悪い · 良い template の lang 指定を避ける方針を示します。
vue/no-template-shadow 悪い · 良い テンプレート変数が外側の名前を隠す箇所を検出します。
vue/no-template-target-blank 悪い · 良い target=_blank の外部リンクに適切な rel を指定します。
vue/no-textarea-mustache 悪い · 良い textarea 内の mustache を検出し、v-model の使用を勧めます。
vue/no-undefined-refs 悪い · 良い テンプレート内の未定義変数参照を検出します。
vue/no-unsafe-url 悪い · 良い 危険なスキームを含む可能性がある URL 属性やバインディングを検出します。
vue/no-unsandboxed-iframe 悪い · 良い iframe に sandbox 属性を指定します。
vue/no-unused-components 悪い · 良い 登録しているのにテンプレートで使わないコンポーネントを検出します。
vue/no-unused-properties 悪い · 良い defineProps に宣言しているのに使わない prop を検出します。
vue/no-unused-refs 悪い · 良い テンプレートに宣言しているのに参照しない ref を検出します。
vue/no-unused-setup-bindings 悪い · 良い script setup に宣言しているのに読み取らない変数を検出します。
vue/no-unused-vars 悪い · 良い v-for / v-slot に宣言しているのに使わない変数を検出します。
vue/no-use-v-else-with-v-for 悪い · 良い 同じ要素での v-else / v-else-if と v-for の併用を検出します。
vue/no-use-v-if-with-v-for 悪い · 良い 同じ要素での v-if と v-for の併用を検出します。
vue/no-useless-mustaches 悪い · 良い 文字列リテラルだけの不要な mustache を検出します。
vue/no-useless-template-attributes 悪い · 良い template 要素の効果がない属性を検出します。
vue/no-useless-v-bind 悪い · 良い 文字列リテラルだけの不要な v-bind を検出します。
vue/no-v-for-template-key-on-child 悪い · 良い template v-for の key を子ではなく template に指定します。
vue/no-v-html 悪い · 良い XSS を防ぐため、v-html を使用した箇所に警告を出します。
vue/no-v-text 悪い · 良い v-text の代わりに mustache を使う方針を適用します。
vue/no-v-text-v-html-on-component 悪い · 良い コンポーネントでの v-text / v-html を検出します。
vue/permitted-contents 悪い · 良い HTML の要素ごとのコンテンツモデルを検査します。
vue/prefer-props-shorthand 悪い · 良い Vue 3.4 の同名 prop バインディングの省略形を使います。
vue/prefer-true-attribute-shorthand 悪い · 良い true を指定するバインディングを真偽属性の省略形にします。
vue/prop-name-casing 悪い · 良い 宣言する prop 名の形式を揃えます。
vue/require-component-is 悪い · 良い 動的 component 要素に :is を指定します。
vue/require-component-registration 悪い · 良い 使用するコンポーネントを import または登録します。
vue/require-scoped-style 悪い · 良い style に scoped を指定する方針を適用します。
vue/require-toggle-inside-transition 悪い · 良い transition の子要素に表示を切り替える条件を指定します。
vue/require-v-for-key 悪い · 良い v-for に安定した :key を指定します。
vue/scoped-event-names 悪い · 良い イベント名を context:event の形式に揃えます。
vue/sfc-element-order 悪い · 良い SFC のトップレベルブロックを設定した順に並べます。
vue/single-style-block 悪い · 良い SFC の style を一つのブロックにまとめます。
vue/slot-name-casing 悪い · 良い 名前付きスロットを kebab-case に揃えます。
vue/this-in-template 悪い · 良い テンプレートで不要な this. 参照を検出します。
vue/use-unique-element-ids 悪い · 良い 静的 ID の代わりに useId() で一意な ID を生成します。
vue/use-v-on-exact 悪い · 良い 修飾子付きのイベント操作と競合するハンドラーに .exact を指定します。
vue/v-bind-style 悪い · 良い v-bind の表記形式を揃えます。
vue/v-on-event-hyphenation 悪い · 良い コンポーネントのカスタムイベント名を設定した形式に揃えます。
vue/v-on-handler-style 悪い · 良い イベントハンドラーの書き方を参照または関数の形式に揃えます。
vue/v-on-style 悪い · 良い v-on の表記形式を揃えます。
vue/v-slot-style 悪い · 良い v-slot の表記形式を揃えます。
vue/valid-attribute-name 悪い · 良い 有効な属性名を指定します。
vue/valid-template-root 悪い · 良い Vue 3 のフラグメントに対応する有効なテンプレートルートを検査します。
vue/valid-v-bind 悪い · 良い v-bind の引数・値・修飾子を検査します。
vue/valid-v-cloak 悪い · 良い v-cloak の引数・値・修飾子を検査します。
vue/valid-v-else 悪い · 良い v-else の位置・引数・値を検査します。
vue/valid-v-else-if 悪い · 良い v-else-if の位置・引数・値を検査します。
vue/valid-v-for 悪い · 良い v-for の式と変数宣言を検査します。
vue/valid-v-html 悪い · 良い v-html の値・引数・修飾子を検査します。
vue/valid-v-if 悪い · 良い v-if に有効な条件式を指定します。
vue/valid-v-is 悪い · 良い v-is の適用先・引数・値を検査します。
vue/valid-v-memo 悪い · 良い v-memo の値を配列の式にします。
vue/valid-v-model 悪い · 良い v-model の値・引数・修飾子を検査します。
vue/valid-v-on 悪い · 良い v-on のイベント名・式・修飾子を検査します。
vue/valid-v-once 悪い · 良い v-once の引数・値・修飾子を検査します。
vue/valid-v-pre 悪い · 良い v-pre の引数・値・修飾子を検査します。
vue/valid-v-show 悪い · 良い v-show に有効な条件式を指定します。
vue/valid-v-slot 悪い · 良い v-slot の適用先・宣言・修飾子を検査します。
vue/valid-v-text 悪い · 良い v-text の値・引数・修飾子を検査します。
vue/warn-custom-block 悪い · 良い SFC のカスタムブロックを検出します。
vue/warn-custom-directive 悪い · 良い 登録が必要なカスタムディレクティブを検出します。

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

vue/a11y-img-alt

画像に代替テキストの alt 属性を指定します。

悪い例 · 良い例

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

設定(Vite+)

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

export default defineConfig({
  vue: {
    linter: {
      "preset": "incremental",
      "rules": {
        "vue/a11y-img-alt": "warn"
      }
    },
  },
});
vp run lint

悪い

静的な画像にも src をバインドする画像にも alt がありません。

<template>
<img src="/photo.jpg" />
<img :src="photo" />
</template>

良い

情報を伝える画像には内容を説明する alt テキスト、装飾画像には空の alt を指定します。動的な画像には説明をバインドします。

<template>
<!-- Informative image -->
<img src="/photo.jpg" alt="Team photo from company retreat" />

<!-- Decorative image (empty alt) -->
<img src="/decoration.svg" alt="" />

<!-- Dynamic alt -->
<img :src="photo" :alt="photoDescription" />
</template>

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

実装 · 全ルール

vue/attribute-hyphenation

コンポーネントの 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/attribute-hyphenation": "warn"
      }
    },
  },
});
vp run lint

悪い

コンポーネントの属性名を camelCase の firstName にしています。

<template>
<UserCard firstName="Ada" />
</template>

良い

first-name に変更し、設定されたハイフン区切りの属性名の方針に合わせます。

<template>
<UserCard first-name="Ada" />
</template>

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

実装 · 全ルール

vue/attribute-order

テンプレートの属性を一定の順に並べます。

悪い例 · 良い例

既定の重大度: 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/attribute-order": "warn"
      }
    },
  },
});
vp run lint

悪い

構造を決める v-if と通常の id 属性より前に、イベントハンドラーを指定しています。

<template>
  <div @click="onClick" v-if="show" id="main"></div>
</template>

良い

v-if、id、イベントハンドラーの順に並べ、ルールの順序に合わせます。

<template>
  <div v-if="show" id="main" @click="onClick"></div>
</template>

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

実装 · 全ルール

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/html-button-has-type

button に有効な type を明示します。

悪い例 · 良い例

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

設定(Vite+)

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

export default defineConfig({
  vue: {
    linter: {
      "preset": "incremental",
      "rules": {
        "vue/html-button-has-type": "warn"
      }
    },
  },
});
vp run lint

悪い

一つは type を省略し、もう一つは対応しない foo を指定しています。

<template>
<button>Click</button>
<button type="foo">Click</button>
</template>

良い

button、submit、reset を明示します。バインドする type は動的な値として扱います。

<template>
<button type="button">Click</button>
<button type="submit">Save</button>
<button type="reset">Reset</button>
<button :type="dynamicType">Click</button>
</template>

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

実装 · 全ルール

vue/html-quotes

HTML 属性値の引用符を揃えます。

悪い例 · 良い例

既定の重大度: 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/html-quotes": "warn"
      }
    },
  },
});
vp run lint

悪い

属性の値にシングルクォートを使うか、クォートを省略しています。

<template>
  <div class='foo'></div>
  <div class=foo></div>
  <div v-if='ready'></div>
</template>

良い

通常の属性とディレクティブの式をダブルクォートで囲みます。

<template>
  <div class="foo"></div>
  <div v-if="ready"></div>
</template>

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

実装 · 全ルール

vue/html-self-closing

要素の種類ごとに自己終了タグの形式を揃えます。

悪い例 · 良い例

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

設定(Vite+)

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

export default defineConfig({
  vue: {
    linter: {
      "preset": "incremental",
      "rules": {
        "vue/html-self-closing": "warn"
      }
    },
  },
});
vp run lint

悪い

空のコンポーネントを開始タグと終了タグの組で書き、img と br に設定された自己終了タグの表記を使っていません。

<template>
  <MyComponent></MyComponent>
  <img>
  <br>
</template>

良い

コンポーネントと void 要素を自己終了タグで書きます。内容がある div は終了タグを残します。

<template>
  <MyComponent />
  <div></div>
  <div />
  <img />
  <br />
  <div>content</div>
</template>

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

実装 · 全ルール

vue/max-template-complexity

コンポーネント自身のテンプレートの複雑度を制限します。

悪い例 · 良い例

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

悪い例のサイクロマティック複雑度は 13、認知的複雑度は 25 で、閾値 11 と 16 を超えます。コンポーネント単位で計測し、対象はインライン HTML テンプレートです。

例の二つの値の計算内訳は複雑度の計算とコンポーネントの境界を参照してください。

設定(Vite+)

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

export default defineConfig({
  vue: {
    linter: {
      "preset": "incremental",
      "rules": {
        "vue/max-template-complexity": "warn"
      }
    },
  },
});
vp run lint

悪い

親のテンプレートに記述した分岐、ループ、スロットの内容、式内の条件分岐により、サイクロマティック複雑度が 13、認知的複雑度が 25 となり、既定の閾値 11 と 16 を超えています。

<script setup lang="ts">
defineProps<{ rows: Row[] }>();
</script>
<template>
  <section>
    <h1>{{ user ? user.name : 'Guest' }}</h1>
    <DataTable :rows="rows">
      <template #cell="{ row, column }">
        <span v-if="column.key === 'status'" :class="row.active ? 'on' : 'off'">{{ row.status ?? 'unknown' }}</span>
        <a v-else-if="column.key === 'link' && row.url" :href="row.url">{{ row.label }}</a>
        <template v-else>
          <em v-for="tag in row.tags" :key="tag">
            <b v-if="tag.pinned || tag.starred">{{ tag.hot ? '!' : '' }}</b>
          </em>
        </template>
      </template>
    </DataTable>
    <p v-if="!rows.length && !loading">No data</p>
  </section>
</template>

良い

描画を RowList に分け、親には v-if を一つ残します。親自身のサイクロマティック複雑度は 2、認知的複雑度は 1 になります。

<template>
  <RowList v-if="ready" :rows="rows" />
</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/mustache-interpolation-spacing

mustache 内の空白を揃えます。

悪い例 · 良い例

既定の重大度: 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/mustache-interpolation-spacing": "warn"
      }
    },
  },
});
vp run lint

悪い

補間の式と区切りの間で、片側または両側の空白がありません。

<template>
  <div>{{text}}</div>
  <div>{{ text}}</div>
  <div>{{text }}</div>
</template>

良い

式と mustache の開始・終了の区切りの間に、それぞれ空白を入れます。

<template>
  <div>{{ text }}</div>
  <div>{{ foo.bar }}</div>
  <div>{{ foo + bar }}</div>
</template>

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

実装 · 全ルール

vue/no-array-index-key

v-for の配列インデックスをそのまま key に使う箇所を検出します。

悪い例 · 良い例

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

設定(Vite+)

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

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

悪い

配列内の現在の位置を key に使っているため、並び替えると同じ項目に割り当てる key が変わります。

<template>
<li v-for="(item, index) in items" :key="index">{{ item.name }}</li>
</template>

良い

item.id を key に使い、位置が変わっても同じ項目に同じ key を割り当てます。

<template>
<li v-for="item in items" :key="item.id">{{ item.name }}</li>
</template>

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

実装 · 全ルール

vue/no-bare-strings-in-template

テンプレートに直接書かれた、国際化の対象となるテキストを検出します。

悪い例 · 良い例

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

設定(Vite+)

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

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

悪い

表示するテキストや利用者向けの説明を指定する属性に、翻訳されない文字列を直接書いています。

<template>
<div>hello</div>
<img alt="a cat" />
<input placeholder="Search" />
<button title="Close">x</button>
</template>

良い

翻訳する内容を $t で取得します。記号だけ、数値だけの内容は例外です。

<template>
<div>{{ $t('hello') }}</div>
<img :alt="$t('cat')" />
<div>-</div>
<div>123</div>
<button :title="$t('close')">{{ $t('x') }}</button>
</template>

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

実装 · 全ルール

vue/no-boolean-attr-value

HTML の真偽属性に不要な値を指定した箇所を検出します。

悪い例 · 良い例

既定の重大度: warning
プリセット: nuxt, opinionated
自動修正: 対応している診断で利用できます
適用範囲: Vue SFC のテンプレートと各ブロック。ルールに必要な script の文脈も例に含めています。
オプション: ルール固有のオプションはありません。重大度とプリセットは設定できます。

設定(Vite+)

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

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

悪い

真偽属性の disabled と checked に、不要な文字列の値を指定しています。

<template>
  <input disabled="disabled" />
  <input checked="checked" />
  <button disabled="true">Save</button>
</template>

良い

値を付けず、真偽属性があることだけで同じ状態を表します。

<template>
  <input disabled />
  <input checked />
  <button disabled>Save</button>
</template>

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

実装 · 全ルール

vue/no-child-content

v-html / v-text と子コンテンツを同時に指定する箇所を検出します。

悪い例 · 良い例

既定の重大度: 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-child-content": "error"
      }
    },
  },
});
vp run lint

悪い

v-text が p の内容を置き換えるため、中に書いたフォールバック用のテキストは表示されません。

<template>
  <p v-text="message">Fallback text</p>
</template>

良い

子のテキストを取り除き、p の内容を v-text だけで指定します。

<template>
  <p v-text="message" />
</template>

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

実装 · 全ルール

vue/no-deprecated-filter

Vue 2 のパイプによるフィルター構文を検出します。

悪い例 · 良い例

既定の重大度: 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-deprecated-filter": "error"
      }
    },
  },
});
vp run lint

悪い

capitalize を適用するために、廃止されたフィルターのパイプ構文を使っています。

<template>
{{ message | capitalize }}
</template>

良い

通常の式で capitalize(message) を呼び出します。

<template>
{{ capitalize(message) }}
</template>

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

実装 · 全ルール

vue/no-deprecated-functional-template

SFC の template で削除済みの functional 属性を検出します。

悪い例 · 良い例

既定の重大度: 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-deprecated-functional-template": "error"
      }
    },
  },
});
vp run lint

悪い

SFC の template に廃止された functional を指定し、旧来の props 経由の参照を使っています。

<template functional>
  <div>{{ props.msg }}</div>
</template>

良い

functional を取り除き、コンポーネントの msg を直接参照します。

<template>
  <div>{{ msg }}</div>
</template>

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

実装 · 全ルール

vue/no-deprecated-html-element-is

通常の HTML 要素で旧形式の 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/no-deprecated-html-element-is": "error"
      }
    },
  },
});
vp run lint

悪い

標準の div で、接頭辞がない旧来の is 属性から Vue コンポーネントを指定しています。

<template>
  <div is="MyComponent" />
</template>

良い

動的な component では :is を使い、標準要素では vue: の接頭辞を明示します。

<template>
  <component :is="MyComponent" />
  <div is="vue:MyComponent" />
</template>

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

実装 · 全ルール

vue/no-deprecated-inline-template

削除済みの inline-template 属性を検出します。

悪い例 · 良い例

既定の重大度: 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-deprecated-inline-template": "error"
      }
    },
  },
});
vp run lint

悪い

Card に渡す内容に、廃止された inline-template を指定しています。

<template>
<Card inline-template><p>Details</p></Card>
</template>

良い

inline-template を取り除き、同じ内容を通常の形で渡します。

<template>
<Card><p>Details</p></Card>
</template>

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

実装 · 全ルール

router-link の削除済み tag 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-deprecated-router-link-tag-prop": "error"
      }
    },
  },
});
vp run lint

悪い

RouterLink の廃止された tag prop で button を指定しています。

<template>
  <router-link to="/home" tag="button">Home</router-link>
</template>

良い

スロットから navigate を受け取り、明示的に記述した button のクリック時に呼び出します。

<template>
  <router-link to="/home" v-slot="{ navigate }">
    <button @click="navigate">Home</button>
  </router-link>
</template>

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

実装 · 全ルール

vue/no-deprecated-scope-attribute

template の削除済み scope 属性を検出します。

悪い例 · 良い例

既定の重大度: 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-deprecated-scope-attribute": "error"
      }
    },
  },
});
vp run lint

悪い

スロットの template に、廃止された scope で props を宣言しています。

<template>
<Card><template scope="props">{{ props.name }}</template></Card>
</template>

良い

現在のデフォルトスロットのディレクティブで、同じ props を受け取ります。

<template>
<Card><template #default="props">{{ props.name }}</template></Card>
</template>

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

実装 · 全ルール

vue/no-deprecated-slot-attribute

削除済みの slot 属性を検出します。

悪い例 · 良い例

既定の重大度: 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-deprecated-slot-attribute": "error"
      }
    },
  },
});
vp run lint

悪い

旧来の slot 属性で header のスロットを選んでいます。

<template>
  <Foo>
    <template slot="header"><h1>Title</h1></template>
    <div :slot="name">Title</div>
  </Foo>
</template>

良い

現在の v-slot:header で header のスロットを指定します。

<template>
  <Foo>
    <template v-slot:header><h1>Title</h1></template>
  </Foo>
</template>

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

実装 · 全ルール

vue/no-deprecated-slot-scope-attribute

削除済みの slot-scope 属性を検出します。

悪い例 · 良い例

既定の重大度: 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-deprecated-slot-scope-attribute": "error"
      }
    },
  },
});
vp run lint

悪い

廃止された slot-scope でスロットの props を受け取っています。

<template>
<Card><template slot-scope="props">{{ props.name }}</template></Card>
</template>

良い

#default で同じ props を受け取り、slot-scope を取り除きます。

<template>
<Card><template #default="props">{{ props.name }}</template></Card>
</template>

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

実装 · 全ルール

vue/no-deprecated-v-bind-sync

削除済みの v-bind の .sync 修飾子を検出します。

悪い例 · 良い例

既定の重大度: 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-deprecated-v-bind-sync": "error"
      }
    },
  },
});
vp run lint

悪い

.camel と組み合わせたものも含め、廃止された .sync を使っています。

<template>
<MyComponent :title.sync="title" />
<MyComponent v-bind:title.sync="title" />
<MyComponent :title.sync.camel="title" />
</template>

良い

一方向なら通常の title のバインディング、更新の受け取りが必要なら v-model:title を使います。

<template>
<MyComponent :title="title" />
<MyComponent v-model:title="title" />
</template>

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

実装 · 全ルール

vue/no-deprecated-v-is

非推奨の v-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/no-deprecated-v-is": "error"
      }
    },
  },
});
vp run lint

悪い

Vue 3.1 で非推奨になった v-is で、描画するコンポーネントを切り替えています。

<template>
<tr v-is="'MyRow'"></tr>
</template>

良い

vue: プレフィックス付きの is 属性、または <component :is> で切り替えます。

<template>
<tr is="vue:MyRow"></tr>
<component :is="MyRow" />
</template>

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

実装 · 全ルール

vue/no-deprecated-v-on-native-modifier

削除済みの v-on の .native 修飾子を検出します。

悪い例 · 良い例

既定の重大度: 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-deprecated-v-on-native-modifier": "error"
      }
    },
  },
});
vp run lint

悪い

コンポーネントのイベントに、廃止された .native を指定しています。

<template>
<MyComponent @click.native="handler" />
<MyComponent v-on:click.native="handler" />
<MyComponent @click.native.stop="handler" />
</template>

良い

.native を取り除き、.stop などの他の修飾子は残します。

<template>
<MyComponent @click="handler" />
<MyComponent @click.stop="handler" />
</template>

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

実装 · 全ルール

vue/no-deprecated-v-on-number-modifiers

v-on の削除済みの数値 keyCode 修飾子を検出します。

悪い例 · 良い例

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

数値修飾子の選択と修正

最初に十進整数として読み取れる修飾子だけを判定します。@keyup.13.27="submit" では 13 を報告し、@keyup.enter.27="submit" に修正します。次の修正で 27 を escape にできます。 @keyup.13suffix="submit" も @keyup.enter="submit" に修正します。0〜9 は対象外のため、 @keyup.0.13="submit" はこのルールでは報告しません。999 など未知のコードは報告だけ行います。 Vue 2 と petite-vue では従来どおり報告しません。

設定(Vite+)

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

export default defineConfig({
  vue: {
    linter: {
      "preset": "incremental",
      "rules": {
        "vue/no-deprecated-v-on-number-modifiers": "error"
      }
    },
  },
});
vp run lint

悪い

キーを、廃止された数値コード 13 と 27 で指定しています。

<template>
<input @keyup.13="submit" />
<input v-on:keyup.27="cancel" />
<input @keyup.13.stop="submit" />
</template>

良い

キーの名前を使い、enter と esc の修飾子に変更します。

<template>
<input @keyup.enter="submit" />
<input @keyup.esc="cancel" />
</template>

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

実装 · 全ルール

vue/no-dupe-v-else-if

v-if / v-else-if の条件重複を検出します。

悪い例 · 良い例

既定の重大度: 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-dupe-v-else-if": "error"
      }
    },
  },
});
vp run lint

悪い

最初と同じ ready の条件を else-if に書き、後の分岐に到達できません。

<template>
  <p v-if="status === 'ready'">Ready</p>
  <p v-else-if="status === 'ready'">Still ready</p>
</template>

良い

二つ目で別の loading の状態を検査し、else-if に到達できる条件にします。

<template>
  <p v-if="status === 'ready'">Ready</p>
  <p v-else-if="status === 'loading'">Loading</p>
</template>

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

実装 · 全ルール

vue/no-duplicate-attributes

同じ要素の属性重複を検出します。

悪い例 · 良い例

既定の重大度: 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-duplicate-attributes": "error"
      }
    },
  },
});
vp run lint

悪い

一つの button に class を二回指定しています。

<template>
  <button class="primary" class="large">Save</button>
</template>

良い

二つのクラスを一つの class 属性にまとめます。

<template>
  <button class="primary large">Save</button>
</template>

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

実装 · 全ルール

vue/no-empty-component-block

空の SFC ブロックを検出します。

悪い例 · 良い例

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

設定(Vite+)

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

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

悪い

template、script、style のブロックが空か、空白だけです。

<template></template>

<script></script>

<style>
</style>

良い

残すブロックには、マークアップ、script の宣言、style の宣言を入れます。

<template>
  <div>Hello</div>
</template>

<script setup>
const message = "Hello";
</script>

<style scoped>
.button { color: red; }
</style>

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

実装 · 全ルール

vue/no-inline-style

インラインの style 属性を検出します。

悪い例 · 良い例

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

設定(Vite+)

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

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

悪い

静的な style 属性に色の宣言を直接書いています。

<template>
  <div style="color: red">Text</div>
</template>

良い

固定した色にはクラスを使います。ratio に依存する幅の動的な style は、静的属性の検査の対象外です。

<template>
  <div class="text-red">Text</div>
  <span :class="{ 'text-red': isRed }">Text</span>
  <div :style="{ width: `${ratio}%` }">Text</div>
</template>

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

実装 · 全ルール

vue/no-invalid-html-attribute

静的 HTML 属性の無効な値を検出します。現在は rel が対象です。

悪い例 · 良い例

既定の重大度: 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-invalid-html-attribute": "warn"
      }
    },
  },
});
vp run lint

悪い

a の rel に、スタイルシートを参照する link 要素用の stylesheet を指定しています。

<template>
<a href="/guide" rel="stylesheet">Guide</a>
</template>

良い

a の rel に、ヘルプへの参照を表す help を指定します。

<template>
<a href="/guide" rel="help">Guide</a>
</template>

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

実装 · 全ルール

vue/no-lone-template

不要な template 要素を検出します。

悪い例 · 良い例

既定の重大度: 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-lone-template": "warn"
      }
    },
  },
});
vp run lint

悪い

内側の template には、構造を指定するディレクティブやスロットとしての役割がありません。

<template>
<div><template><p>Details</p></template></div>
</template>

良い

不要な template を取り除き、div に p を直接入れます。

<template>
<div><p>Details</p></div>
</template>

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

実装 · 全ルール

vue/no-multi-spaces

連続する不要な空白を検出します。

悪い例 · 良い例

既定の重大度: 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-multi-spaces": "warn"
      }
    },
  },
});
vp run lint

悪い

属性同士や、要素名と最初の属性の間に空白が二つあります。

<template>
  <div  class="panel"></div>
  <div class="panel"  id="main"></div>
</template>

良い

同じ class と id 属性を保ち、属性間の連続した空白を一つの空白に揃えます。

<template>
  <div class="panel"></div>
  <div class="panel" id="main"></div>
</template>

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

実装 · 全ルール

vue/no-multiple-objects-in-class

:class 配列内の複数のオブジェクト指定をまとめます。

悪い例 · 良い例

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

設定(Vite+)

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

export default defineConfig({
  vue: {
    linter: {
      "preset": "incremental",
      "rules": {
        "vue/no-multiple-objects-in-class": "warn"
      }
    },
  },
});
vp run lint

悪い

class の配列に、まとめられるオブジェクトリテラルを二つ直接指定しています。

<template>
<div :class="[{ a }, { b }]"></div>
<div :class="[{ active: isActive }, { error: hasError }]"></div>
</template>

良い

条件を一つのオブジェクトにまとめます。オブジェクト一つと文字列の組み合わせや、リテラル以外の要素を持つ配列も許可されます。

<template>
<div :class="{ a, b }"></div>
<div :class="[{ active: isActive }, 'static']"></div>
<div :class="[foo, bar]"></div>
</template>

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

実装 · 全ルール

vue/no-multiple-template-root

単一ルートを要求するテンプレートで複数ルートを検出します。

悪い例 · 良い例

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

単一ルートを要求する場合に有効にします。通常の Vue 3 は複数ルートを許可します。

設定(Vite+)

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

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

悪い

単一ルートを要求する設定で、テンプレートのルートに p が二つ並んでいます。

<template>
<p>First</p>
<p>Second</p>
</template>

良い

section で囲み、ルートを一つにします。単一ルートを前提とする場合にだけ有効にする規約です。

<template>
<section><p>First</p><p>Second</p></section>
</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-negated-v-if-condition

v-else がある条件分岐の否定条件を反転して読みやすくします。

悪い例 · 良い例

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

設定(Vite+)

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

export default defineConfig({
  vue: {
    linter: {
      "preset": "incremental",
      "rules": {
        "vue/no-negated-v-if-condition": "warn"
      }
    },
  },
});
vp run lint

悪い

v-else と対になる v-if を、否定した条件で始めています。

<template>
<div v-if="!ok">A</div>
<div v-else>B</div>
</template>

良い

先に否定していない ok の条件を使います。条件を反転する際は分岐の内容も入れ替えます。単独の否定の v-if や !== の比較は許可されます。

<template>
<div v-if="ok">B</div>
<div v-else>A</div>

<div v-if="!ok">A</div>

<div v-if="a !== b">A</div>
<div v-else>B</div>
</template>

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

実装 · 全ルール

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-preprocessor-lang

CSS プリプロセッサーより標準の CSS を使う方針を示します。

悪い例 · 良い例

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

設定(Vite+)

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

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

悪い

style の lang に SCSS を指定しているため、プリプロセッサーを禁止するルールが記述されたブロックを報告します。

<template><p>Notice</p></template>
<style lang="scss">
.notice { color: red; }
</style>

良い

同じ宣言を、プリプロセッサーの lang を指定せずに通常の CSS で記述します。

<template><p>Notice</p></template>
<style>
.notice { color: red; }
</style>

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

実装 · 全ルール

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-root-v-if

テンプレートの単一ルートに v-if を指定する箇所を検出します。

悪い例 · 良い例

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

設定(Vite+)

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

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

悪い

コンポーネントのルート自体を v-if で表示・非表示にしています。

<template>
  <div v-if="show">content</div>
</template>

良い

外側の div をルートとして残し、内側の p に表示条件を指定します。

<template>
  <div>
    <p v-if="show">content</p>
  </div>
</template>

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

実装 · 全ルール

vue/no-script-non-standard-lang

script の非標準の lang 指定を避ける方針を示します。

悪い例 · 良い例

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

現在の対応: no-sfc-finding

このカタログ項目は現在の SFC lint では固有の診断を出しません。悪い例・良い例は意図した規約の説明であり、実行時にこのルールの診断が出る例ではありません。ID を設定しても未対応の SFC 検査は追加されません。

設定できる ID(現在の SFC lint では診断されません)

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

export default defineConfig({
  vue: {
    linter: {
      "preset": "incremental",
      "rules": {
        "vue/no-script-non-standard-lang": "warn"
      }
    },
  },
});
vp run lint

悪い

lang=coffee で CoffeeScript の構文を使っています。現在の SFC 検査では、この言語に対してこのルール固有の診断は出ません。

<script lang="coffee">
count = 0
</script>
<template><p>Notice</p></template>

良い

lang=ts と通常の TypeScript の宣言を使い、意図した言語の方針を示します。

<script lang="ts">
const count = 0;
</script>
<template><p>Notice</p></template>

良い例は意図する規約を示します。現在の SFC lint では、悪い例・良い例のどちらからもこのルール固有の診断は出ません。

実装 · 全ルール

vue/no-src-attribute

SFC ブロックの外部 src 指定を検出します。

悪い例 · 良い例

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

設定(Vite+)

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

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

悪い

SFC の template、script、style を src の外部ファイルに分けています。

<template src="./template.html"></template>
<script src="./script.ts"></script>
<style src="./style.css"></style>

良い

各ブロックに内容を記述し、外部の src 属性を使いません。

<template>
  <p>Hello</p>
</template>

<script setup lang="ts">
const label = "Hello";
</script>

<style scoped>
p {
  color: red;
}
</style>

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

実装 · 全ルール

vue/no-static-inline-styles

静的なインライン style 属性を検出します。

悪い例 · 良い例

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

設定(Vite+)

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

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

悪い

p の style 属性に、変化しない色を直接指定しています。

<template>
<p style="color: red">Notice</p>
</template>

良い

notice のクラスと scoped の CSS に、変化しない色を移します。

<template><p class="notice">Notice</p></template>
<style scoped>.notice { color: red; }</style>

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

実装 · 全ルール

vue/no-template-key

v-for 用ではない template の key 指定を検出します。

悪い例 · 良い例

既定の重大度: 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-template-key": "error"
      }
    },
  },
});
vp run lint

悪い

繰り返しではない template に key を指定しています。

<template>
<template :key="section"><div>Details</div></template>
</template>

良い

template の v-for に key を付け、繰り返す各フラグメントを識別します。

<template>
<template v-for="item in items" :key="item.id"><div>{{ item.name }}</div></template>
</template>

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

実装 · 全ルール

vue/no-template-lang

template の lang 指定を避ける方針を示します。

悪い例 · 良い例

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

設定(Vite+)

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

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

悪い

template の lang に Pug を指定しているため、HTML のみを許可するルールが記述されたブロックを報告します。

<template lang="pug">
p Notice
</template>

良い

lang を指定せず、通常の HTML の p を直接記述します。

<template>
<p>Notice</p>
</template>

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

実装 · 全ルール

vue/no-template-shadow

テンプレート変数が外側の名前を隠す箇所を検出します。

悪い例 · 良い例

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

検査はテンプレート内の v-for、v-slot(#name を含む)、従来のスコープ付きスロットの束縛を比較します。外側の束縛を隠す識別子を報告し、同じ要素内では属性が記述された順に比較します。兄弟要素のスコープは独立しています。プロパティのキーや既定値の参照は宣言ではなく、v-pre の部分木は検査しません。

script やコンポーネントのプロパティ名は現在の検査範囲に含みません。同じ名前の script 束縛があるだけで、単独のテンプレート束縛を報告することはありません。診断範囲は、エスケープや HTML エンティティを含む元の識別子を示します。

設定(Vite+)

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

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

悪い

内側の v-for でも item を宣言し、外側の item を隠しています。

<template>
<div v-for="item in items" :key="item.id"><span v-for="item in item.children" :key="item.id">{{ item.name }}</span></div>
</template>

良い

内側は child に変更し、外側の item と内側の child を分けます。

<template>
<div v-for="item in items" :key="item.id"><span v-for="child in item.children" :key="child.id">{{ child.name }}</span></div>
</template>

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

実装 · 全ルール

vue/no-template-target-blank

target=_blank の外部リンクに適切な rel を指定します。

悪い例 · 良い例

既定の重大度: 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-template-target-blank": "warn"
      }
    },
  },
});
vp run lint

悪い

外部リンクを target=_blank で開きますが、必要な rel の保護がありません。

<template>
<a href="https://example.com" target="_blank">x</a>
</template>

良い

同じリンクに noopener noreferrer を指定します。

<template>
<a href="https://example.com" target="_blank" rel="noopener noreferrer">x</a>
</template>

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

実装 · 全ルール

vue/no-textarea-mustache

textarea 内の mustache を検出し、v-model の使用を勧めます。

悪い例 · 良い例

既定の重大度: 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-textarea-mustache": "error"
      }
    },
  },
});
vp run lint

悪い

textarea の値をバインドせず、要素内のテキスト補間に message を記述しています。

<template>
  <textarea>{{ message }}</textarea>
</template>

良い

v-model で、編集可能な textarea の値と message を関連付けます。

<template>
  <textarea v-model="message"></textarea>
</template>

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

実装 · 全ルール

vue/no-undefined-refs

テンプレート内の未定義変数参照を検出します。

悪い例 · 良い例

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

設定(Vite+)

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

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

悪い

script は message しか宣言していませんが、テンプレートが missing を参照しています。

<script setup>const message = "Hello";</script>
<template>{{ missing }}</template>

良い

script setup で宣言済みの message を補間で参照し、未定義の名前を取り除きます。

<script setup>const message = "Hello";</script>
<template>{{ message }}</template>

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

実装 · 全ルール

vue/no-unsafe-url

危険なスキームを含む可能性がある URL 属性やバインディングを検出します。

悪い例 · 良い例

既定の重大度: 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-unsafe-url": "warn"
      }
    },
  },
});
vp run lint

悪い

a の移動先に、JavaScript を実行する javascript: スキームを使っています。

<template>
<a href="javascript:alert(1)">Continue</a>
</template>

良い

移動先を、通常のローカルパス /next に変更します。

<template>
<a href="/next">Continue</a>
</template>

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

実装 · 全ルール

vue/no-unsandboxed-iframe

iframe に sandbox 属性を指定します。

悪い例 · 良い例

既定の重大度: 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-unsandboxed-iframe": "warn"
      }
    },
  },
});
vp run lint

悪い

iframe に sandbox がなく、機能の制限を指定していません。

<template>
<iframe src="/embed"></iframe>
</template>

良い

sandbox で制限し、script が必要な場合にだけ allow-scripts を明示します。

<template>
<iframe src="/embed" sandbox></iframe>
<iframe src="/embed" sandbox="allow-scripts"></iframe>
</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/no-unused-refs

テンプレートに宣言しているのに参照しない ref を検出します。

悪い例 · 良い例

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

設定(Vite+)

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

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

悪い

テンプレートの unused の ref に対応する script の参照がありません。

<template><input ref="unused" /></template>
<script setup>
const x = 1
</script>

良い

inputEl のテンプレート ref に、script setup の同じ名前の ref を対応させます。

<template><input ref="inputEl" /></template>
<script setup>
import { ref } from 'vue'
const inputEl = ref(null)
</script>

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

実装 · 全ルール

vue/no-unused-setup-bindings

script setup に宣言しているのに読み取らない変数を検出します。

悪い例 · 良い例

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

設定(Vite+)

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

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

悪い

script setup の message をテンプレートで使っていません。

<script setup>const message = "Hello";</script>
<template><p>Welcome</p></template>

良い

script setup で宣言した message を p の補間で参照し、未使用の宣言を残しません。

<script setup>const message = "Hello";</script>
<template><p>{{ message }}</p></template>

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

実装 · 全ルール

vue/no-unused-vars

v-for / v-slot に宣言しているのに使わない変数を検出します。

悪い例 · 良い例

既定の重大度: 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-vars": "warn"
      }
    },
  },
});
vp run lint

悪い

ループで使わない index と、スロットで使わない foo を宣言しています。

<template>
  <li v-for="(item, index) in items" :key="item.id">{{ item.name }}</li>
  <template v-slot="{ foo }">
    <span>Hello</span>
  </template>
</template>

良い

index を参照するか、未使用を意図する _index という名前にし、スロットでは data を表示します。index の key は使用例であり、項目の安定した識別子として推奨するものではありません。

<template>
  <li v-for="(item, index) in items" :key="index">{{ item.name }}</li>
  <li v-for="(item, _index) in items" :key="item.id">{{ item.name }}</li>
  <template v-slot="{ data }">
    <span>{{ data }}</span>
  </template>
</template>

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

実装 · 全ルール

vue/no-use-v-else-with-v-for

同じ要素での v-else / v-else-if と v-for の併用を検出します。

悪い例 · 良い例

既定の重大度: 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-use-v-else-with-v-for": "warn"
      }
    },
  },
});
vp run lint

悪い

同じ p に v-else と v-for を指定しています。Vue が受け付ける構文ですが、警告は二つの制御フローを分けることを勧めます。Opinionated と Nuxt に加え、HappyPath と Ecosystem でも既定で有効です。

<template>
<p v-if="ready">Ready</p>
<p v-else v-for="item in items" :key="item.id">{{ item.name }}</p>
</template>

良い

template に v-else を分け、その子の p に v-for を指定します。

<template>
<p v-if="ready">Ready</p>
<template v-else><p v-for="item in items" :key="item.id">{{ item.name }}</p></template>
</template>

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

実装 · 全ルール

vue/no-use-v-if-with-v-for

同じ要素での v-if と v-for の併用を検出します。

悪い例 · 良い例

既定の重大度: 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-use-v-if-with-v-for": "warn"
      }
    },
  },
});
vp run lint

悪い

同じ li に v-if と v-for を指定し、ループの変数で表示条件を検査しています。

<template>
  <li v-for="item in items" v-if="item.visible" :key="item.id">
    {{ item.name }}
  </li>
</template>

良い

computed で表示する項目を先に絞り込み、テンプレートではその配列の各項目を繰り返し描画します。

<script setup lang="ts">
const visibleItems = computed(() => items.filter((item) => item.visible));
</script>

<template>
  <li v-for="item in visibleItems" :key="item.id">
    {{ item.name }}
  </li>
</template>

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

実装 · 全ルール

vue/no-useless-mustaches

文字列リテラルだけの不要な mustache を検出します。

悪い例 · 良い例

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

設定(Vite+)

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

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

悪い

補間の内容が固定の文字列だけで、式の評価が不要です。

<template>
<div>{{ 'x' }}</div>
<div>{{ "x" }}</div>
<div>{{ `x` }}</div>
</template>

良い

固定のテキストは直接書きます。変数、値を埋め込むテンプレート文字列、区切りの空白の補間は残します。

<template>
<div>x</div>
<div>{{ x }}</div>
<div>{{ `pre-${x}` }}</div>
<span>A</span> {{ " " }} <span>B</span>
</template>

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

実装 · 全ルール

vue/no-useless-template-attributes

template 要素の効果がない属性を検出します。

悪い例 · 良い例

既定の重大度: 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-useless-template-attributes": "error"
      }
    },
  },
});
vp run lint

悪い

条件付きの template に class を指定していますが、この構造用のラッパーは DOM 要素を描画しません。

<template>
<section><template v-if="ready" class="notice"><p>Ready</p></template></section>
</template>

良い

実際に表示する p に class を移し、構造を指定する template の v-if は残します。

<template>
<section><template v-if="ready"><p class="notice">Ready</p></template></section>
</template>

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

実装 · 全ルール

vue/no-useless-v-bind

文字列リテラルだけの不要な v-bind を検出します。

悪い例 · 良い例

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

設定(Vite+)

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

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

悪い

foo に固定の文字列か、補間がないテンプレート文字列をバインドしています。

<template>
<div :foo="'bar'"></div>
<div :foo="`bar`"></div>
</template>

良い

固定の値は静的な属性にし、変数や補間がある値はバインディングを残します。

<template>
<div foo="bar"></div>
<div :foo="bar"></div>
<div :foo="`pre-${bar}`"></div>
</template>

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

実装 · 全ルール

vue/no-v-for-template-key-on-child

template v-for の key を子ではなく template に指定します。

悪い例 · 良い例

既定の重大度: 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-v-for-template-key-on-child": "error"
      }
    },
  },
});
vp run lint

悪い

繰り返す template に key がなく、子の p に指定しています。

<template>
<template v-for="item in items"><p :key="item.id">{{ item.name }}</p></template>
</template>

良い

template の v-for に key を移し、繰り返すフラグメント全体を識別します。

<template>
<template v-for="item in items" :key="item.id"><p>{{ item.name }}</p></template>
</template>

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

実装 · 全ルール

vue/no-v-html

XSS を防ぐため、v-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-v-html": "warn"
      }
    },
  },
});
vp run lint

悪い

v-html で content を通常の文字ではなく HTML として扱っています。

<template>
  <article v-html="content" />
</template>

良い

mustache の補間で、HTML を挿入せず content をエスケープしたテキストとして表示します。

<template>
  <article>{{ content }}</article>
</template>

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

実装 · 全ルール

vue/no-v-text

v-text の代わりに mustache を使う方針を適用します。

悪い例 · 良い例

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

設定(Vite+)

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

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

悪い

要素の内容を v-text のディレクティブで指定しています。

<template>
<div v-text="message"></div>
</template>

良い

同じテキストのバインディングを、要素内の mustache に記述します。

<template>
<div>{{ message }}</div>
</template>

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

実装 · 全ルール

vue/no-v-text-v-html-on-component

コンポーネントでの v-text / v-html を検出します。

悪い例 · 良い例

既定の重大度: 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-v-text-v-html-on-component": "error"
      }
    },
  },
});
vp run lint

悪い

コンポーネントに、要素の内容を置き換える v-html や v-text を指定しています。

<template>
  <MyComponent v-html="content" />
  <MyComponent v-text="content" />
</template>

良い

標準の HTML 要素にはディレクティブを使えます。MyComponent にはデフォルトスロットから内容を渡します。

<template>
  <div v-html="content"></div>
  <component is="div" v-html="content" />
  <MyComponent>{{ content }}</MyComponent>
</template>

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

実装 · 全ルール

vue/permitted-contents

HTML の要素ごとのコンテンツモデルを検査します。

悪い例 · 良い例

既定の重大度: error
プリセット: 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/permitted-contents": "error"
      }
    },
  },
});
vp run lint

悪い

p にブロック要素を入れたり、tbody を省略したりしています。操作要素の入れ子や、ul の直下に div を置く例もあります。

<template>
  <p><div>block in a paragraph</div></p>
  <table><tr><td>row without tbody</td></tr></table>
  <a href="#"><button type="button">nested control</button></a>
  <ul><div>not a list item</div></ul>
</template>

良い

p はインラインの内容、table は tbody、ul は li を使います。独自コンポーネントの MyItem は、ul の子となる既知の HTML 要素としては検査されません。

<template>
  <p><span>inline in a paragraph</span></p>
  <table><tbody><tr><td>cell</td></tr></tbody></table>
  <ul><li>list item</li><MyItem /></ul>
</template>

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

実装 · 全ルール

vue/prefer-props-shorthand

Vue 3.4 の同名 prop バインディングの省略形を使います。

悪い例 · 良い例

既定の重大度: warning
プリセット: nuxt, opinionated
自動修正: 対応している診断で利用できます
適用範囲: Vue SFC のテンプレートと各ブロック。ルールに必要な script の文脈も例に含めています。
オプション: ルール固有のオプションはありません。重大度とプリセットは設定できます。

設定(Vite+)

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

export default defineConfig({
  vue: {
    linter: {
      "preset": "incremental",
      "rules": {
        "vue/prefer-props-shorthand": "warn"
      }
    },
  },
});
vp run lint

悪い

ハイフン区切りに対応する camelCase も含め、属性と対応する変数名を式に重複して書いています。

<template>
  <MyComponent :foo="foo" />
  <MyComponent :user-name="userName" />
  <span :style="style" />
  <div :aria-label="ariaLabel" />
</template>

良い

Vue 3.4 以降の同名の省略形で式を省きます。bar のように別の変数を渡す式は明示します。

<template>
  <MyComponent :foo />
  <MyComponent :user-name />
  <span :style />
  <div :aria-label />
  <MyComponent :foo="bar" />
</template>

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

実装 · 全ルール

vue/prefer-true-attribute-shorthand

true を指定するバインディングを真偽属性の省略形にします。

悪い例 · 良い例

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

設定(Vite+)

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

export default defineConfig({
  vue: {
    linter: {
      "preset": "incremental",
      "rules": {
        "vue/prefer-true-attribute-shorthand": "warn"
      }
    },
  },
});
vp run lint

悪い

標準の真偽属性 disabled に、固定の true をバインドしています。

<template>
<input :disabled="true" />
</template>

良い

標準の真偽属性は省略形にします。false のバインディングやコンポーネントの prop は値を残します。

<template>
<input disabled />
<input :disabled="false" />
<MyComponent :visible="true" />
<MyComponent :visible="isVisible" />
</template>

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

実装 · 全ルール

vue/prop-name-casing

宣言する prop 名の形式を揃えます。

悪い例 · 良い例

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

宣言した props の名前を検査します。子に渡す属性名の表記を検査するルールではありません。

設定(Vite+)

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

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

悪い

宣言した prop の user_name をアンダースコア区切りにしています。

<script setup lang="ts">
defineProps<{ user_name: string }>();
</script>
<template><p>{{ user_name }}</p></template>

良い

宣言とテンプレートの参照を、camelCase の userName に揃えます。

<script setup lang="ts">
defineProps<{ userName: string }>();
</script>
<template><p>{{ userName }}</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>

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

実装 · 全ルール

vue/require-scoped-style

style に scoped を指定する方針を適用します。

悪い例 · 良い例

既定の重大度: 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/require-scoped-style": "warn"
      }
    },
  },
});
vp run lint

悪い

.button の style にスコープがなく、他のコンポーネントの一致する要素にも作用します。

<style>
.button {
  color: red;
}
</style>

良い

scoped を style に付け、同じセレクタと宣言に Vue のコンポーネントスコープを適用します。

<style scoped>
.button {
  color: red;
}
</style>

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

実装 · 全ルール

vue/require-toggle-inside-transition

transition の子要素に表示を切り替える条件を指定します。

悪い例 · 良い例

既定の重大度: 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-toggle-inside-transition": "error"
      }
    },
  },
});
vp run lint

悪い

<Transition> 内の静的な子に表示の切り替えや動的な選択がなく、enter / leave が発生する条件がありません。

<template>
<transition>
  <div>content</div>
</transition>
</template>

良い

v-if="show" で子の有無を切り替え、enter / leave の対象にします。

<template>
<transition>
  <div v-if="show">content</div>
</transition>
</template>

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

実装 · 全ルール

vue/require-v-for-key

v-for に安定した :key を指定します。

悪い例 · 良い例

既定の重大度: 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-v-for-key": "error"
      }
    },
  },
});
vp run lint

悪い

繰り返す <li> に key がなく、一覧更新時に対応する項目を識別できません。

<template>
  <li v-for="item in items">{{ item.name }}</li>
</template>

良い

:key="item.id" で、現在の位置ではなく項目の識別子を各ノードに付けます。

<template>
  <li v-for="item in items" :key="item.id">{{ item.name }}</li>
</template>

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

実装 · 全ルール

vue/scoped-event-names

イベント名を context:event の形式に揃えます。

悪い例 · 良い例

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

設定(Vite+)

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

export default defineConfig({
  vue: {
    linter: {
      "preset": "incremental",
      "rules": {
        "vue/scoped-event-names": "warn"
      }
    },
  },
});
vp run lint

悪い

playAudio、pauseAudio、reloadAudio は camelCase の末尾に対象を付けており、このルールのコロン区切りの規約に合いません。

<template>
  <AudioPlayer
    @playAudio="play"
    @pauseAudio="pause"
    @reloadAudio="reload"
  />
</template>

良い

audio:play、audio:pause、audio:reload に audio: のスコープを明示します。emit 側も同じ名前に合わせます。

<template>
  <AudioPlayer
    @audio:play="play"
    @audio:pause="pause"
    @audio:reload="reload"
  />
</template>

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

実装 · 全ルール

vue/sfc-element-order

SFC のトップレベルブロックを設定した順に並べます。

悪い例 · 良い例

既定の重大度: 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/sfc-element-order": "warn"
      }
    },
  },
});
vp run lint

悪い

style が script より前にあり、設定した SFC ブロック順に合いません。

<style scoped>
.panel {
  color: red;
}
</style>
<script setup lang="ts">
const label = "Save";
</script>

良い

script → template → style の順に並べます。型付きオプションで別の順序を選べます。

<script setup lang="ts">
const label = "Save";
</script>

<template>
  <p>{{ label }}</p>
</template>

<style scoped>
p {
  color: red;
}
</style>

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

実装 · 全ルール

vue/single-style-block

SFC の style を一つのブロックにまとめます。

悪い例 · 良い例

既定の重大度: 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/single-style-block": "warn"
      }
    },
  },
});
vp run lint

悪い

panel と title の scoped スタイルを二つの style ブロックに分けています。

<style scoped>
.panel {
  color: red;
}
</style>

<style scoped>
.title {
  color: blue;
}
</style>

良い

両方のセレクタを一つの scoped style にまとめ、どちらのスタイルも残します。

<style scoped>
.panel {
  color: red;
}
.title {
  color: blue;
}
</style>

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

実装 · 全ルール

vue/slot-name-casing

名前付きスロットを kebab-case に揃えます。

悪い例 · 良い例

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

設定(Vite+)

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

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

悪い

名前付きスロット mySlot が camelCase で、ハイフン区切りの規約に合いません。

<template>
<MyCard><template #mySlot>Content</template></MyCard>
</template>

良い

スロット名を kebab-case の #my-slot にします。対応するスロットの出口の名前も合わせます。

<template>
<MyCard><template #my-slot>Content</template></MyCard>
</template>

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

実装 · 全ルール

vue/this-in-template

テンプレートで不要な this. 参照を検出します。

悪い例 · 良い例

既定の重大度: 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/this-in-template": "warn"
      }
    },
  },
});
vp run lint

悪い

テンプレートで直接使えるバインディングを this.message、this.className、this.handleClick と明示的に参照しています。

<template>
<div>{{ this.message }}</div>
<div :class="this.className"></div>
<button @click="this.handleClick()"></button>
</template>

良い

message、className、handleClick を直接使います。文字列 'this.is.a.string' はメンバー参照ではないため残します。

<template>
<div>{{ message }}</div>
<div :class="className"></div>
<button @click="handleClick()"></button>
<div>{{ 'this.is.a.string' }}</div>
</template>

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

実装 · 全ルール

vue/use-unique-element-ids

静的 ID の代わりに useId() で一意な ID を生成します。

悪い例 · 良い例

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

設定(Vite+)

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

export default defineConfig({
  vue: {
    linter: {
      "preset": "incremental",
      "rules": {
        "vue/use-unique-element-ids": "warn"
      }
    },
  },
});
vp run lint

悪い

固定の email ID がコンポーネントの各インスタンスで重複し、複数表示時に label の参照先が曖昧になります。

<template>
  <label for="email">Email</label>
  <input id="email" />
</template>

良い

useId() の emailId を label の for と input の id の両方にバインドします。

<script setup>
import { useId } from "vue";

const emailId = useId();
</script>

<template>
  <label :for="emailId">Email</label>
  <input :id="emailId" />
</template>

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

実装 · 全ルール

vue/use-v-on-exact

修飾子付きのイベント操作と競合するハンドラーに .exact を指定します。

悪い例 · 良い例

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

ハンドラーが重なる条件

ネイティブ要素の同じイベントを処理するリスナーを比較します。独自コンポーネントのイベントは、両方に .native が付いている場合だけ対象です。イベント名が異なる場合や、キーフィルターに共通するキーがない場合は競合しません。

システム修飾子は、押している必要があるキーを指定します。@keydown.alt.shift は Ctrl+Alt+Shift でも動くため、@keydown.alt.ctrl.shift と重なる場合は広い方に .exact を追加します。.exact は指定したシステムキーを許可し、それ以外の Ctrl、Shift、Alt、Meta を拒否します。

複数のキーボード修飾子は選択肢です。@keydown.up.down は上・下のどちらでも動き、Ctrl+下では @keydown.ctrl.down と重なります。診断範囲は .exact が必要なディレクティブのキーで、ハンドラー式は含みません。

設定(Vite+)

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

export default defineConfig({
  vue: {
    linter: {
      "preset": "incremental",
      "rules": {
        "vue/use-v-on-exact": "warn"
      }
    },
  },
});
vp run lint

悪い

通常の click ハンドラーも Ctrl キーを押しながらのクリックで動くため、別の .ctrl ハンドラーと重複します。

<template>
  <button type="button" @click="handleClick" @click.ctrl="handleCtrlClick">
    Save
  </button>
</template>

良い

.exact で通常のハンドラーを修飾キーのない click に限定し、Ctrl 専用のハンドラーと分けます。

<template>
  <button
    type="button"
    @click.exact="handleClick"
    @click.ctrl="handleCtrlClick"
  >
    Save
  </button>
</template>

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

実装 · 全ルール

vue/v-bind-style

v-bind の表記形式を揃えます。

悪い例 · 良い例

既定の重大度: 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/v-bind-style": "warn"
      }
    },
  },
});
vp run lint

悪い

v-bind:class が長い形式で、設定で指定したコロンによる省略形の規約に合いません。

<template>
  <div v-bind:class="panelClass"></div>
</template>

良い

同じ式を :class にします。値の型ではなくディレクティブの書き方を検査するルールです。

<template>
  <div :class="panelClass"></div>
</template>

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

実装 · 全ルール

vue/v-on-event-hyphenation

コンポーネントのカスタムイベント名を設定した形式に揃えます。

悪い例 · 良い例

既定の重大度: 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/v-on-event-hyphenation": "warn"
      }
    },
  },
});
vp run lint

悪い

カスタムコンポーネントのリスナーがハイフン区切りではなく @myEvent です。

<template>
<MyComponent @myEvent="handler" />
<MyComponent v-on:myEvent="handler" />
<my-component @update:modelValue="handler" />
</template>

良い

@my-event に変更します。例のネイティブ要素のリスナーと動的なイベント引数はこの検査の対象外です。

<template>
<MyComponent @my-event="handler" />
<div @myEvent="handler" />
<MyComponent @[dynamicEvent]="handler" />
</template>

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

実装 · 全ルール

vue/v-on-handler-style

イベントハンドラーの書き方を参照または関数の形式に揃えます。

悪い例 · 良い例

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

設定(Vite+)

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

export default defineConfig({
  vue: {
    linter: {
      "preset": "incremental",
      "rules": {
        "vue/v-on-handler-style": "warn"
      }
    },
  },
});
vp run lint

悪い

イベント属性の中に変更処理や複数の文を直接記述しています。

<template>
<button @click="count++"></button>
<button @click="doThis(); doThat()"></button>
<button @click="foo = bar"></button>
</template>

良い

handler などの関数への参照を使うか、インライン処理が必要ならアロー関数や function 式で関数の境界を明示します。

<template>
<button @click="handler"></button>
<button @click="foo.bar"></button>
<button @click="() => count++"></button>
<button @click="function () { count++ }"></button>
</template>

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

実装 · 全ルール

vue/v-on-style

v-on の表記形式を揃えます。

悪い例 · 良い例

既定の重大度: 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/v-on-style": "warn"
      }
    },
  },
});
vp run lint

悪い

v-on:click が長い形式で、このルールの省略形に合いません。

<template>
  <div v-on:click="handleClick"></div>
</template>

良い

ハンドラーを変えずに @click の省略形を使います。

<template>
  <div @click="handleClick"></div>
</template>

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

実装 · 全ルール

vue/v-slot-style

v-slot の表記形式を揃えます。

悪い例 · 良い例

既定の重大度: 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/v-slot-style": "warn"
      }
    },
  },
});
vp run lint

悪い

コンポーネントで #default、template で v-slot:header を使い、場所ごとの規約と逆になっています。

<template>
  <MyComponent #default="props">{{ props.item }}</MyComponent>
  <MyComponent>
    <template v-slot:header>Header</template>
  </MyComponent>
</template>

良い

コンポーネントのデフォルトスロットは v-slot、template の名前付きスロットは #header にします。

<template>
  <MyComponent v-slot="props">{{ props.item }}</MyComponent>
  <MyComponent>
    <template #header>Header</template>
  </MyComponent>
</template>

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

実装 · 全ルール

vue/valid-attribute-name

有効な属性名を指定します。

悪い例 · 良い例

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

悪い例での診断: parser/template

不正な属性名は、この防御的なルールに届く前に parser/template で検出されます。悪い例で確認するのは parser/template の検出で、vue/valid-attribute-name が別に出るとは限りません。

設定(Vite+)

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

export default defineConfig({
  vue: {
    linter: {
      "preset": "incremental",
      "rules": {
        "vue/valid-attribute-name": "error"
      }
    },
  },
});
vp run lint

悪い

my"attr の引用符で属性名が壊れています。この例の診断は parser/template で、別のルール診断が出ることを示すものではありません。

<template>
<div my"attr="value"></div>
</template>

良い

my-attr は正しい属性名で、テンプレートパーサーが属性と値を読み取れます。

<template>
<div my-attr="value"></div>
</template>

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

実装 · 全ルール

vue/valid-template-root

Vue 3 のフラグメントに対応する有効なテンプレートルートを検査します。

悪い例 · 良い例

既定の重大度: 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/valid-template-root": "error"
      }
    },
  },
});
vp run lint

悪い

描画上の役割を与えるディレクティブがない通常の <template> を、テンプレートのルートに置いています。

<template>
  <template>content</template>
</template>

良い

描画される <div> をルートにします。Vue 3 のフラグメント全般を一つのルートに制限する例ではありません。

<template>
  <div>content</div>
</template>

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

実装 · 全ルール

vue/valid-v-bind

v-bind の引数・値・修飾子を検査します。

悪い例 · 良い例

既定の重大度: 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/valid-v-bind": "error"
      }
    },
  },
});
vp run lint

悪い

引数のない v-bind にオブジェクト式がなく、空の引数形式には属性名がありません。

<template>
  <div v-bind></div>
  <div :></div>
</template>

良い

属性と式を指定するか、オブジェクトをバインドします。Vue 3.4 以降では :loading の同名省略形も使えます。

<template>
  <div :class="panelClass"></div>
  <div v-bind="{ class: panelClass }"></div>
  <div :loading></div>
</template>

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

実装 · 全ルール

vue/valid-v-cloak

v-cloak の引数・値・修飾子を検査します。

悪い例 · 良い例

既定の重大度: 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/valid-v-cloak": "error"
      }
    },
  },
});
vp run lint

悪い

値・引数・修飾子を受け取らない v-cloak に、それらを指定しています。

<template>
<div v-cloak="foo"></div>
<div v-cloak:arg></div>
<div v-cloak.mod></div>
</template>

良い

値のない v-cloak を使います。マウント後に Vue が属性を除くまで CSS で非表示にできます。

<template>
<div v-cloak></div>
</template>

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

実装 · 全ルール

vue/valid-v-else

v-else の位置・引数・値を検査します。

悪い例 · 良い例

既定の重大度: 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/valid-v-else": "error"
      }
    },
  },
});
vp run lint

悪い

v-else に式を渡す、v-if と併用する、直前の条件分岐がない、といった不正な組み合わせです。

<template>
  <div v-else="ready"></div>
  <div v-else v-if="ready"></div>
  <div v-else></div>
</template>

良い

対応する v-if の直後に、値のない v-else を置きます。

<template>
  <div v-if="ready"></div>
  <div v-else></div>
</template>

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

実装 · 全ルール

vue/valid-v-else-if

v-else-if の位置・引数・値を検査します。

悪い例 · 良い例

既定の重大度: 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/valid-v-else-if": "error"
      }
    },
  },
});
vp run lint

悪い

v-else-if の直前に条件分岐がない、条件式がない、引数や修飾子を渡している、といった不正な書き方です。

<template>
<div v-else-if="foo"></div> <!-- without preceding v-if -->
<div v-if="foo"></div><div v-else-if></div>
<div v-if="foo"></div><div v-else-if:arg="bar"></div>
<div v-if="foo"></div><div v-else-if.mod="bar"></div>
</template>

良い

先行する v-if または v-else-if の直後に、条件式を持つ v-else-if を置きます。

<template>
<div v-if="foo"></div>
<div v-else-if="bar"></div>
</template>

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

実装 · 全ルール

vue/valid-v-for

v-for の式と変数宣言を検査します。

悪い例 · 良い例

既定の重大度: 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/valid-v-for": "error"
      }
    },
  },
});
vp run lint

悪い

繰り返し式がないか、対応していない .stop 修飾子を付けています。

<template>
  <div v-for></div>
  <div v-for=""></div>
  <div v-for.stop="item in items"></div>
</template>

良い

item in items や (item, index) of items の完全な式と、例の key を使います。

<template>
  <div v-for="item in items" :key="item.id"></div>
  <div v-for="(item, index) of items" :key="index"></div>
</template>

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

実装 · 全ルール

vue/valid-v-html

v-html の値・引数・修飾子を検査します。

悪い例 · 良い例

既定の重大度: 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/valid-v-html": "error"
      }
    },
  },
});
vp run lint

悪い

v-html の式がないか、対応していない引数・修飾子を指定しています。

<template>
<div v-html></div>
<div v-html:arg="foo"></div>
<div v-html.mod="foo"></div>
</template>

良い

v-html="html" で正しい式を渡します。構文が正しくても HTML の無害化や信頼できない内容の安全性は保証されません。

<template>
<div v-html="html"></div>
</template>

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

実装 · 全ルール

vue/valid-v-if

v-if に有効な条件式を指定します。

悪い例 · 良い例

既定の重大度: 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/valid-v-if": "error"
      }
    },
  },
});
vp run lint

悪い

条件式がないか、同じノードに v-if と else 分岐のディレクティブを併記しています。

<template>
  <div v-if></div>
  <div v-if=""></div>
  <div v-if="ready" v-else></div>
</template>

良い

ready や count > 0 の式を各 v-if に指定し、競合する else 分岐のディレクティブを除きます。

<template>
  <div v-if="ready"></div>
  <div v-if="count > 0"></div>
</template>

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

実装 · 全ルール

vue/valid-v-is

v-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/valid-v-is": "error"
      }
    },
  },
});
vp run lint

悪い

v-is に引数や修飾子を渡す、値がない、ネイティブの HTML 要素ではなくコンポーネントに指定している、といった不正な書き方です。

<template>
<tr v-is:arg="'MyRow'"></tr>
<tr v-is.mod="'MyRow'"></tr>
<tr v-is></tr>
<MyComponent v-is="'MyRow'" />
</template>

良い

<tr> などのネイティブ要素に値付きの v-is を指定し、代わりに描画するコンポーネントを示します。

<template>
<tr v-is="'MyRow'"></tr>
</template>

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

実装 · 全ルール

vue/valid-v-memo

v-memo の値を配列の式にします。

悪い例 · 良い例

既定の重大度: 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/valid-v-memo": "error"
      }
    },
  },
});
vp run lint

悪い

値のない v-memo では、サブツリーを再利用する判断に必要な依存式を渡せません。

<template>
  <div v-memo></div>
</template>

良い

v-memo="[valueA, valueB]" でメモ化に使う依存配列を渡します。

<template>
  <div v-memo="[valueA, valueB]">{{ label }}</div>
</template>

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

実装 · 全ルール

vue/valid-v-model

v-model の値・引数・修飾子を検査します。

悪い例 · 良い例

既定の重大度: 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/valid-v-model": "error"
      }
    },
  },
});
vp run lint

悪い

ネイティブの <div> にはフォーム要素として v-model を使えません。また、input に値なしで指定したディレクティブには、書き込み先の式がありません。

<template>
  <div v-model="value"></div>
  <input v-model />
</template>

良い

input、select、textarea、カスタムコンポーネントを例の書き込み可能な変数にバインドします。

<template>
  <input v-model="value" />
  <select v-model="selected"></select>
  <textarea v-model="text"></textarea>
  <MyInput v-model="value" />
</template>

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

実装 · 全ルール

vue/valid-v-on

v-on のイベント名・式・修飾子を検査します。

悪い例 · 良い例

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

修飾子の検証

未対応の修飾子は、修飾子の名前ごとに報告します。長い v-on:click、動的なイベント引数、オブジェクト形式も対象です。受け付ける名前は eslint-plugin-vue 10.9.2 に合わせ、Vue 組み込みのイベント修飾子、完全なキー別名一覧、単一の Unicode コードポイント、有限な十進整数の接頭辞を持つ名前です。整数は JavaScript の Number.parseInt(name, 10) と同じように読み取るため、.13suffix もこのルールでは有効です。数値キーの非推奨判定と .native の移行診断は別のルールが担当します。

ハンドラーなしで動作するのは .stop と .prevent だけです。.once、.enter、設定した独自の名前にもハンドラー式が必要です。

独自のイベント処理で使う名前は vue.linter.ruleOptions に追加できます。

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

export default defineConfig({}).withVue({
  linter: {
    rules: { "vue/valid-v-on": "error" },
    ruleOptions: { "vue/valid-v-on": { modifiers: ["custom"] } },
  },
});

これにより @click.custom="handler" を使えます。名前は大文字と小文字を区別して完全一致で比較し、組み込みの名前に追加します。ルール自体が無効な場合は有効にしません。範囲別の設定では継承した一覧を置き換え、[] でリセットできます。

キーの一覧は、MIT ライセンスの eslint-plugin-vue のキー別名 を元にしています。出典とライセンスは実装とともに保持しています。

設定(Vite+)

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

export default defineConfig({
  vue: {
    linter: {
      "preset": "incremental",
      "rules": {
        "vue/valid-v-on": "error"
      },
      "ruleOptions": {
        "vue/valid-v-on": {
          "modifiers": [
            "custom"
          ]
        }
      }
    },
  },
});
vp run lint

悪い

イベント引数または必要なハンドラー・オブジェクト式がありません。

<template>
  <div v-on></div>
  <div @></div>
  <div @click></div>
  <div @click.sync="handleClick"></div>
  <div @click.nativeish="handleClick"></div>
  <div @click.once></div>
</template>

良い

イベントとハンドラーを指定するか、引数なしの v-on にリスナーのオブジェクトを渡します。

<template>
  <div @click="handleClick"></div>
  <form @submit.prevent></form>
  <input @keyup.page-down="handlePageDown" />
  <input @keyup.あ="handleKey" />
  <div v-on="{ click: handleClick }"></div>
</template>

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

実装 · 全ルール

vue/valid-v-once

v-once の引数・値・修飾子を検査します。

悪い例 · 良い例

既定の重大度: 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/valid-v-once": "error"
      }
    },
  },
});
vp run lint

悪い

一度だけ描画する印である v-once に、値・引数・修飾子を渡しています。

<template>
<div v-once="foo"></div>
<div v-once:arg></div>
<div v-once.mod></div>
</template>

良い

値のない v-once で、サブツリーを一度だけ描画する対象にします。

<template>
<div v-once></div>
</template>

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

実装 · 全ルール

vue/valid-v-pre

v-pre の引数・値・修飾子を検査します。

悪い例 · 良い例

既定の重大度: 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/valid-v-pre": "error"
      }
    },
  },
});
vp run lint

悪い

コンパイルを省く印である v-pre に、引数・修飾子・値を渡しています。

<template>
<div v-pre:arg></div>
<div v-pre.mod></div>
<div v-pre="foo"></div>
</template>

良い

値のない v-pre でサブツリーをコンパイル対象から外し、マスタッシュをそのまま表示します。

<template>
<div v-pre>{{ raw }}</div>
</template>

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

実装 · 全ルール

vue/valid-v-show

v-show に有効な条件式を指定します。

悪い例 · 良い例

既定の重大度: 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/valid-v-show": "error"
      }
    },
  },
});
vp run lint

悪い

v-show に表示条件の式がないか、display を変更する DOM 要素のない <template> に付けています。

<template>
  <div v-show></div>
  <template v-show="ready"><div></div></template>
</template>

良い

<div> のような描画される要素に表示条件を指定します。

<template>
  <div v-show="ready"></div>
  <div v-show="count > 0"></div>
</template>

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

実装 · 全ルール

vue/valid-v-slot

v-slot の適用先・宣言・修飾子を検査します。

悪い例 · 良い例

既定の重大度: 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/valid-v-slot": "error"
      }
    },
  },
});
vp run lint

悪い

ネイティブの <div> にスロットのディレクティブを付けるか、他のデフォルトスロットや名前付きスロットの宣言と競合させています。

<template>
  <div v-slot:header></div>
  <MyComponent v-slot v-slot:header />
  <template v-slot:header v-slot:footer />
</template>

良い

デフォルトスロットはコンポーネント上、名前付きスロットは子の <template #header> に宣言します。

<template>
  <MyComponent v-slot="{ item }">{{ item }}</MyComponent>
  <MyComponent>
    <template #header>Header</template>
  </MyComponent>
</template>

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

実装 · 全ルール

vue/valid-v-text

v-text の値・引数・修飾子を検査します。

悪い例 · 良い例

既定の重大度: 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/valid-v-text": "error"
      }
    },
  },
});
vp run lint

悪い

v-text に文字列の式がないか、対応していない引数・修飾子を指定しています。

<template>
<div v-text></div>
<div v-text:arg="foo"></div>
<div v-text.mod="foo"></div>
</template>

良い

v-text="msg" は構文として有効です。別の vue/no-v-text は mustache の使用を推奨する場合があります。

<template>
<div v-text="msg"></div>
</template>

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

実装 · 全ルール

vue/warn-custom-block

SFC のカスタムブロックを検出します。

悪い例 · 良い例

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

設定(Vite+)

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

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

悪い

SFC に <i18n> のカスタムブロックがあり、通常の template / script / style 処理とは別の連携が必要です。

<i18n>
{ "en": { "hello": "Hello" } }
</i18n>

<template>
  <p>{{ hello }}</p>
</template>

良い

標準の template と script setup を使います。移植性に関するこの任意の警告は、カスタムブロック全般が Vue で無効という意味ではありません。

<template>
  <p>{{ hello }}</p>
</template>

<script setup lang="ts">
const hello = "Hello";
</script>

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

実装 · 全ルール

vue/warn-custom-directive

登録が必要なカスタムディレクティブを検出します。

悪い例 · 良い例

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

設定(Vite+)

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

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

悪い

v-focus、v-mask、v-click-outside はプロジェクト固有のディレクティブの実装を必要とし、この任意の規約で警告されます。

<template>
  <input v-focus />
  <input v-mask="'###-####'" />
  <div v-click-outside="handleClose"></div>
</template>

良い

組み込みの v-if、v-model、v-on を使います。規約を無効にすれば、正しく登録したカスタムディレクティブは有効な Vue として使えます。

<template>
  <div v-if="ready"></div>
  <input v-model="value" />
  <button type="button" @click="onClick">Save</button>
</template>

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

実装 · 全ルール