Vue rules
Every Vue rule has its purpose, configuration, Bad and Good examples on this page. Highlighted lines show the change; copied code keeps the complete source.
| Rule | Examples | Purpose |
|---|---|---|
vue/a11y-img-alt |
Bad · Good | Require alt attribute on images for accessibility |
vue/attribute-hyphenation |
Bad · Good | Enforce attribute naming style on custom components |
vue/attribute-order |
Bad · Good | Enforce a consistent order of attributes |
vue/component-definition-name-casing |
Bad · Good | Enforce PascalCase or kebab-case for component definition names |
vue/component-name-in-template-casing |
Bad · Good | Enforce specific casing for component names in templates |
vue/html-button-has-type |
Bad · Good | Require an explicit valid type on button elements |
vue/html-quotes |
Bad · Good | Enforce quotes style of HTML attributes |
vue/html-self-closing |
Bad · Good | Enforce self-closing style |
vue/max-template-complexity |
Bad · Good | Limit a component's own template complexity (cyclomatic and cognitive) |
vue/multi-word-component-names |
Bad · Good | Require component names to be multi-word |
vue/mustache-interpolation-spacing |
Bad · Good | Enforce consistent spacing inside mustache interpolations |
vue/no-array-index-key |
Bad · Good | Disallow using the v-for index variable directly as the :key |
vue/no-bare-strings-in-template |
Bad · Good | Disallow raw human-readable text in the template that should be internationalized |
vue/no-boolean-attr-value |
Bad · Good | Disallow explicit values for boolean HTML attributes |
vue/no-child-content |
Bad · Good | Disallow child content when using v-html or v-text |
vue/no-deprecated-filter |
Bad · Good | Disallow deprecated Vue 2 filter syntax using the pipe operator |
vue/no-deprecated-functional-template |
Bad · Good | Disallow the functional attribute on the SFC <template> |
vue/no-deprecated-html-element-is |
Bad · Good | Disallow the is attribute on native HTML elements |
vue/no-deprecated-inline-template |
Bad · Good | Disallow the deprecated inline-template attribute |
vue/no-deprecated-router-link-tag-prop |
Bad · Good | Disallow the tag prop on <router-link> |
vue/no-deprecated-scope-attribute |
Bad · Good | Disallow the deprecated scope attribute on <template> |
vue/no-deprecated-slot-attribute |
Bad · Good | Disallow the deprecated slot attribute |
vue/no-deprecated-slot-scope-attribute |
Bad · Good | Disallow the deprecated slot-scope attribute |
vue/no-deprecated-v-bind-sync |
Bad · Good | Disallow the deprecated .sync modifier on v-bind |
vue/no-deprecated-v-on-native-modifier |
Bad · Good | Disallow the deprecated .native modifier on v-on |
vue/no-deprecated-v-on-number-modifiers |
Bad · Good | Disallow deprecated numeric keyCode modifiers on v-on |
vue/no-dupe-v-else-if |
Bad · Good | Disallow duplicate conditions in v-if / v-else-if chains |
vue/no-duplicate-attributes |
Bad · Good | Disallow duplicate attributes on the same element |
vue/no-empty-component-block |
Bad · Good | Disallow empty SFC blocks |
vue/no-inline-style |
Bad · Good | Discourage use of inline style attributes |
vue/no-invalid-html-attribute |
Bad · Good | Disallow invalid static values for HTML attributes |
vue/no-lone-template |
Bad · Good | Disallow unnecessary <template> elements |
vue/no-multi-spaces |
Bad · Good | Disallow multiple consecutive spaces |
vue/no-multiple-objects-in-class |
Bad · Good | Disallow multiple object literals inside a :class array binding |
vue/no-multiple-template-root |
Bad · Good | Disallow multiple root nodes in a template |
vue/no-mutating-props |
Bad · Good | Disallow mutating component props |
vue/no-negated-v-if-condition |
Bad · Good | Disallow a negated v-if condition when the chain has a v-else |
vue/no-non-component-keep-alive-child |
Bad · Good | Disallow plain element wrappers directly below <KeepAlive> |
vue/no-preprocessor-lang |
Bad · Good | Discourage CSS preprocessor usage in favor of modern CSS |
vue/no-reserved-component-names |
Bad · Good | Disallow the use of reserved names as component names |
vue/no-root-v-if |
Bad · Good | Disallow v-if on the single root element of a template |
vue/no-script-non-standard-lang |
Bad · Good | Discourage non-standard script lang values |
vue/no-src-attribute |
Bad · Good | Discourage src attribute on SFC blocks |
vue/no-static-inline-styles |
Bad · Good | Disallow static inline style attributes |
vue/no-template-key |
Bad · Good | Disallow key attribute on <template> |
vue/no-template-lang |
Bad · Good | Discourage lang attribute on template block |
vue/no-template-shadow |
Bad · Good | Disallow variable names that shadow variables in outer scope |
vue/no-template-target-blank |
Bad · Good | Disallow target="_blank" without rel="noopener noreferrer" |
vue/no-textarea-mustache |
Bad · Good | Disallow mustache interpolation in <textarea> |
vue/no-undefined-refs |
Bad · Good | Disallow undefined variable references in templates |
vue/no-unsafe-url |
Bad · Good | Warn about potentially unsafe URL bindings |
vue/no-unsandboxed-iframe |
Bad · Good | Require a sandbox attribute on iframe elements |
vue/no-unused-components |
Bad · Good | Disallow registering components that are not used inside templates |
vue/no-unused-properties |
Bad · Good | Disallow unused properties defined in defineProps |
vue/no-unused-refs |
Bad · Good | Report template refs (ref="x") never referenced in <script> |
vue/no-unused-setup-bindings |
Bad · Good | Disallow unread script setup bindings |
vue/no-unused-vars |
Bad · Good | Disallow unused variable definitions in v-for and v-slot directives |
vue/no-use-v-else-with-v-for |
Bad · Good | Disallow using v-else-if or v-else on the same element as v-for |
vue/no-use-v-if-with-v-for |
Bad · Good | Disallow using v-if on the same element as v-for |
vue/no-useless-mustaches |
Bad · Good | Disallow a mustache interpolation whose expression is a constant string literal |
vue/no-useless-template-attributes |
Bad · Good | Disallow useless attributes on <template> elements |
vue/no-useless-v-bind |
Bad · Good | Disallow a v-bind whose value is a plain string literal |
vue/no-v-for-template-key-on-child |
Bad · Good | Disallow key on the child of a <template v-for> |
vue/no-v-html |
Bad · Good | Warn against v-html to prevent XSS vulnerabilities |
vue/no-v-text |
Bad · Good | Disallow the v-text directive; prefer mustache interpolation |
vue/no-v-text-v-html-on-component |
Bad · Good | Disallow v-text / v-html on component elements |
vue/permitted-contents |
Bad · Good | Enforce HTML content model rules |
vue/prefer-props-shorthand |
Bad · Good | Recommend shorthand syntax for props (Vue 3.4+) |
vue/prefer-true-attribute-shorthand |
Bad · Good | Prefer the shorthand for a boolean attribute bound to true |
vue/prop-name-casing |
Bad · Good | Enforce a casing for declared prop names |
vue/require-component-is |
Bad · Good | Require v-bind:is on <component> elements |
vue/require-component-registration |
Bad · Good | Require explicit import or registration for components |
vue/require-scoped-style |
Bad · Good | Require scoped attribute on style tags |
vue/require-toggle-inside-transition |
Bad · Good | Require a toggle on the element wrapped by <transition> |
vue/require-v-for-key |
Bad · Good | Require v-bind:key with v-for directives |
vue/scoped-event-names |
Bad · Good | Recommend scoped event names using context:event format |
vue/sfc-element-order |
Bad · Good | Enforce consistent order of SFC top-level elements |
vue/single-style-block |
Bad · Good | Recommend having a single style block |
vue/slot-name-casing |
Bad · Good | Enforce kebab-case for named slots used via v-slot |
vue/this-in-template |
Bad · Good | Disallow this. in template expressions |
vue/use-unique-element-ids |
Bad · Good | Enforce unique element IDs using useId() instead of static literals |
vue/use-v-on-exact |
Bad · Good | Enforce .exact modifier on v-on when there are modifier-based handlers |
vue/v-bind-style |
Bad · Good | Enforce v-bind directive style |
vue/v-on-event-hyphenation |
Bad · Good | Enforce hyphenation of custom event names in v-on on components |
vue/v-on-handler-style |
Bad · Good | Enforce writing v-on handlers as a method reference or an inline function |
vue/v-on-style |
Bad · Good | Enforce v-on directive style |
vue/v-slot-style |
Bad · Good | Enforce v-slot directive style |
vue/valid-attribute-name |
Bad · Good | Require valid attribute names |
vue/valid-template-root |
Bad · Good | Enforce a valid <template> root for Vue 3 fragment semantics |
vue/valid-v-bind |
Bad · Good | Enforce valid v-bind directives |
vue/valid-v-cloak |
Bad · Good | Enforce valid v-cloak directives |
vue/valid-v-else |
Bad · Good | Enforce valid v-else directives |
vue/valid-v-for |
Bad · Good | Enforce valid v-for directives |
vue/valid-v-html |
Bad · Good | Enforce valid v-html directives |
vue/valid-v-if |
Bad · Good | Enforce valid v-if directives |
vue/valid-v-memo |
Bad · Good | Enforce valid v-memo directives |
vue/valid-v-model |
Bad · Good | Enforce valid v-model directives |
vue/valid-v-on |
Bad · Good | Enforce valid v-on directives |
vue/valid-v-once |
Bad · Good | Enforce valid v-once directives |
vue/valid-v-show |
Bad · Good | Enforce valid v-show directives |
vue/valid-v-slot |
Bad · Good | Enforce valid v-slot directives |
vue/valid-v-text |
Bad · Good | Enforce valid v-text directives |
vue/warn-custom-block |
Bad · Good | Warn about custom blocks in SFC files |
vue/warn-custom-directive |
Bad · Good | Warn about custom directives that need registration |
All rules · Rule Options · ESLint migration map · Project checks · Attributes across components
vue/a11y-img-alt
Require alt attribute on images for accessibility
Default severity: warning
Presets: none
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/a11y-img-alt": "warn"
}
},
},
});
vp run lint
Bad
Neither the static image nor the dynamically sourced image supplies an alt attribute.
<template>
<img src="/photo.jpg" />
<img :src="photo" />
</template>
Good
Informative images get descriptive alt text, decoration gets an empty alt, and the dynamic image binds its description.
<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>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
vue/attribute-hyphenation
Enforce attribute naming style on custom components
Default severity: warning
Presets: happy-path, nuxt, ecosystem, opinionated
Automatic fix: Available for supported findings
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: See typed options and defaults.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/attribute-hyphenation": "warn"
}
},
},
});
vp run lint
Bad
The component attribute uses the camelCase spelling firstName.
<template>
<UserCard firstName="Ada" />
</template>
Good
The first-name spelling follows the configured hyphenated component-attribute convention.
<template>
<UserCard first-name="Ada" />
</template>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
vue/attribute-order
Enforce a consistent order of attributes
Default severity: warning
Presets: happy-path, nuxt, ecosystem, opinionated
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/attribute-order": "warn"
}
},
},
});
vp run lint
Bad
The event handler appears before the structural v-if directive and ordinary id attribute.
<template>
<div @click="onClick" v-if="show" id="main"></div>
</template>
Good
v-if comes first, followed by id and then the event handler, following the rule ordering.
<template>
<div v-if="show" id="main" @click="onClick"></div>
</template>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
vue/component-definition-name-casing
Enforce PascalCase or kebab-case for component definition names
Default severity: warning
Presets: happy-path, nuxt, ecosystem, opinionated
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
The component filename is checked. PascalCase and kebab-case are accepted; mixed casing is reported.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/component-definition-name-casing": "warn"
}
},
},
});
vp run lint
Bad
The filename myComponent.vue mixes a lowercase initial with an internal uppercase letter instead of using PascalCase or kebab-case.
myComponent.vue
<template><p>Content</p></template>
Good
Renaming the file to MyComponent.vue uses PascalCase; its template content is unchanged.
MyComponent.vue
<template><p>Content</p></template>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
vue/component-name-in-template-casing
Enforce specific casing for component names in templates
Default severity: warning
Presets: nuxt, opinionated
Automatic fix: Available for supported findings
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: See typed options and defaults.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/component-name-in-template-casing": "warn"
}
},
},
});
vp run lint
Bad
The component is written in kebab-case and camelCase under the PascalCase convention.
<script setup>
import MyComponent from "./MyComponent.vue";
</script>
<template>
<my-component />
<myComponent />
</template>
Good
MyComponent uses PascalCase; native slot syntax remains lowercase.
<script setup>
import MyComponent from "./MyComponent.vue";
</script>
<template>
<MyComponent />
<RouterView />
<slot />
</template>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
vue/html-button-has-type
Require an explicit valid type on button elements
Default severity: warning
Presets: nuxt, opinionated
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/html-button-has-type": "warn"
}
},
},
});
vp run lint
Bad
One button omits type and another supplies the unsupported foo type.
<template>
<button>Click</button>
<button type="foo">Click</button>
</template>
Good
Buttons specify button, submit, or reset; a bound type is treated as dynamic.
<template>
<button type="button">Click</button>
<button type="submit">Save</button>
<button type="reset">Reset</button>
<button :type="dynamicType">Click</button>
</template>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
vue/html-quotes
Enforce quotes style of HTML attributes
Default severity: warning
Presets: happy-path, nuxt, ecosystem, opinionated
Automatic fix: Available for supported findings
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/html-quotes": "warn"
}
},
},
});
vp run lint
Bad
The attributes use single quotes or no quotes instead of the double-quote convention.
<template>
<div class='foo'></div>
<div class=foo></div>
<div v-if='ready'></div>
</template>
Good
Both ordinary attributes and directive expressions use double quotes.
<template>
<div class="foo"></div>
<div v-if="ready"></div>
</template>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
vue/html-self-closing
Enforce self-closing style
Default severity: warning
Presets: nuxt, opinionated
Automatic fix: Available for supported findings
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: See typed options and defaults.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/html-self-closing": "warn"
}
},
},
});
vp run lint
Bad
The empty component uses a closing pair, while void img and br elements omit the configured self-closing spelling.
<template>
<MyComponent></MyComponent>
<img>
<br>
</template>
Good
The component and void elements use self-closing syntax; a div with content retains its closing tag.
<template>
<MyComponent />
<div></div>
<div />
<img />
<br />
<div>content</div>
</template>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
vue/max-template-complexity
Limit a component's own template complexity (cyclomatic and cognitive)
Default severity: warning
Presets: none
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
Bad has cyclomatic complexity 13 and cognitive complexity 25 (limits: 11 and 16). Each component is measured separately; only inline HTML templates are supported.
See complexity scoring and component boundaries for the contributions behind the example's two scores.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/max-template-complexity": "warn"
}
},
},
});
vp run lint
Bad
The parent-authored branches, loop, slot content, and expression decisions produce scores of 13 and 25, above the default limits 11 and 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>
Good
The parent template delegates rendering to RowList and keeps one v-if; its own scores are 2 and 1.
<template>
<RowList v-if="ready" :rows="rows" />
</template>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
vue/multi-word-component-names
Require component names to be multi-word
Default severity: error
Presets: essential, nuxt, opinionated
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
The filename is the finding. Rename the same component; changing a child tag does not fix it.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/multi-word-component-names": "error"
}
},
},
});
vp run lint
Bad
Item.vue gives the component a single-word name.
Item.vue
<template><p>Item</p></template>
Good
TodoItem.vue gives the same template a multi-word component name.
TodoItem.vue
<template><p>Item</p></template>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
vue/mustache-interpolation-spacing
Enforce consistent spacing inside mustache interpolations
Default severity: warning
Presets: happy-path, nuxt, ecosystem, opinionated
Automatic fix: Available for supported findings
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/mustache-interpolation-spacing": "warn"
}
},
},
});
vp run lint
Bad
The text interpolation is missing a space at one or both delimiter boundaries.
<template>
<div>{{text}}</div>
<div>{{ text}}</div>
<div>{{text }}</div>
</template>
Good
Spaces separate the expression from both opening and closing mustache delimiters.
<template>
<div>{{ text }}</div>
<div>{{ foo.bar }}</div>
<div>{{ foo + bar }}</div>
</template>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
vue/no-array-index-key
Disallow using the v-for index variable directly as the :key
Default severity: warning
Presets: nuxt, opinionated
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/no-array-index-key": "warn"
}
},
},
});
vp run lint
Bad
The list key is its current index, so item identity changes when the list is reordered.
<template>
<li v-for="(item, index) in items" :key="index">{{ item.name }}</li>
</template>
Good
The key comes from item.id, preserving the identity of each item across position changes.
<template>
<li v-for="item in items" :key="item.id">{{ item.name }}</li>
</template>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
vue/no-bare-strings-in-template
Disallow raw human-readable text in the template that should be internationalized
Default severity: warning
Presets: none
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/no-bare-strings-in-template": "warn"
}
},
},
});
vp run lint
Bad
Visible text and naming attributes embed untranslated strings directly in the template.
<template>
<div>hello</div>
<img alt="a cat" />
<input placeholder="Search" />
<button title="Close">x</button>
</template>
Good
Translatable content calls $t; the punctuation and numeric-only examples are allowed exceptions.
<template>
<div>{{ $t('hello') }}</div>
<img :alt="$t('cat')" />
<div>-</div>
<div>123</div>
<button :title="$t('close')">{{ $t('x') }}</button>
</template>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
vue/no-boolean-attr-value
Disallow explicit values for boolean HTML attributes
Default severity: warning
Presets: nuxt, opinionated
Automatic fix: Available for supported findings
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/no-boolean-attr-value": "warn"
}
},
},
});
vp run lint
Bad
The boolean disabled and checked attributes redundantly contain string values.
<template>
<input disabled="disabled" />
<input checked="checked" />
<button disabled="true">Save</button>
</template>
Good
The presence of each boolean attribute expresses the same enabled state without a value.
<template>
<input disabled />
<input checked />
<button disabled>Save</button>
</template>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
vue/no-child-content
Disallow child content when using v-html or v-text
Default severity: error
Presets: essential, happy-path, nuxt, ecosystem, opinionated
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/no-child-content": "error"
}
},
},
});
vp run lint
Bad
v-text replaces the paragraph content, so the authored fallback text cannot survive that directive.
<template>
<p v-text="message">Fallback text</p>
</template>
Good
Removing the child text leaves v-text as the single source of paragraph content.
<template>
<p v-text="message" />
</template>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
vue/no-deprecated-filter
Disallow deprecated Vue 2 filter syntax using the pipe operator
Default severity: error
Presets: none
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/no-deprecated-filter": "error"
}
},
},
});
vp run lint
Bad
The pipe uses the removed Vue filter syntax to apply capitalize.
<template>
{{ message | capitalize }}
</template>
Good
Calling capitalize(message) applies the transformation as an ordinary expression.
<template>
{{ capitalize(message) }}
</template>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
vue/no-deprecated-functional-template
Disallow the functional attribute on the SFC <template>
Default severity: error
Presets: ecosystem, essential, happy-path, nuxt, opinionated
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/no-deprecated-functional-template": "error"
}
},
},
});
vp run lint
Bad
The SFC template has the removed functional attribute and reads the old props context.
<template functional>
<div>{{ props.msg }}</div>
</template>
Good
The ordinary template omits functional and reads the component binding msg directly.
<template>
<div>{{ msg }}</div>
</template>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
vue/no-deprecated-html-element-is
Disallow the is attribute on native HTML elements
Default severity: error
Presets: none
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/no-deprecated-html-element-is": "error"
}
},
},
});
vp run lint
Bad
A native div uses the old unprefixed is attribute to request a Vue component.
<template>
<div is="MyComponent" />
</template>
Good
A dynamic component uses :is; the native-element spelling explicitly uses the vue: prefix.
<template>
<component :is="MyComponent" />
<div is="vue:MyComponent" />
</template>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
vue/no-deprecated-inline-template
Disallow the deprecated inline-template attribute
Default severity: error
Presets: none
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/no-deprecated-inline-template": "error"
}
},
},
});
vp run lint
Bad
Card uses the deprecated inline-template attribute for its supplied content.
<template>
<Card inline-template><p>Details</p></Card>
</template>
Good
The same content is passed normally without the inline-template attribute.
<template>
<Card><p>Details</p></Card>
</template>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
vue/no-deprecated-router-link-tag-prop
Disallow the tag prop on <router-link>
Default severity: error
Presets: none
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/no-deprecated-router-link-tag-prop": "error"
}
},
},
});
vp run lint
Bad
RouterLink uses the removed tag prop to request a button element.
<template>
<router-link to="/home" tag="button">Home</router-link>
</template>
Good
The slot provides navigate to an explicitly authored button.
<template>
<router-link to="/home" v-slot="{ navigate }">
<button @click="navigate">Home</button>
</router-link>
</template>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
vue/no-deprecated-scope-attribute
Disallow the deprecated scope attribute on <template>
Default severity: error
Presets: essential, happy-path, nuxt, ecosystem, opinionated
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/no-deprecated-scope-attribute": "error"
}
},
},
});
vp run lint
Bad
The slot template declares props through the deprecated scope attribute.
<template>
<Card><template scope="props">{{ props.name }}</template></Card>
</template>
Good
The default-slot directive declares the same props binding through current slot syntax.
<template>
<Card><template #default="props">{{ props.name }}</template></Card>
</template>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
vue/no-deprecated-slot-attribute
Disallow the deprecated slot attribute
Default severity: error
Presets: essential, happy-path, nuxt, ecosystem, opinionated
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/no-deprecated-slot-attribute": "error"
}
},
},
});
vp run lint
Bad
The header slot is selected through the old slot attribute.
<template>
<Foo>
<template slot="header"><h1>Title</h1></template>
<div :slot="name">Title</div>
</Foo>
</template>
Good
v-slot:header explicitly selects the header slot with the current directive.
<template>
<Foo>
<template v-slot:header><h1>Title</h1></template>
</Foo>
</template>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
vue/no-deprecated-slot-scope-attribute
Disallow the deprecated slot-scope attribute
Default severity: error
Presets: essential, happy-path, nuxt, ecosystem, opinionated
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/no-deprecated-slot-scope-attribute": "error"
}
},
},
});
vp run lint
Bad
The template receives slot props through the deprecated slot-scope attribute.
<template>
<Card><template slot-scope="props">{{ props.name }}</template></Card>
</template>
Good
The #default directive receives those props without slot-scope.
<template>
<Card><template #default="props">{{ props.name }}</template></Card>
</template>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
vue/no-deprecated-v-bind-sync
Disallow the deprecated .sync modifier on v-bind
Default severity: error
Presets: essential, happy-path, nuxt, ecosystem, opinionated
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/no-deprecated-v-bind-sync": "error"
}
},
},
});
vp run lint
Bad
The bindings use the removed .sync modifier, including its combination with .camel.
<template>
<MyComponent :title.sync="title" />
<MyComponent v-bind:title.sync="title" />
<MyComponent :title.sync.camel="title" />
</template>
Good
Use an ordinary one-way title binding or v-model:title when an update channel is required.
<template>
<MyComponent :title="title" />
<MyComponent v-model:title="title" />
</template>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
vue/no-deprecated-v-on-native-modifier
Disallow the deprecated .native modifier on v-on
Default severity: error
Presets: essential, happy-path, nuxt, ecosystem, opinionated
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/no-deprecated-v-on-native-modifier": "error"
}
},
},
});
vp run lint
Bad
The component handlers use the removed .native event modifier.
<template>
<MyComponent @click.native="handler" />
<MyComponent v-on:click.native="handler" />
<MyComponent @click.native.stop="handler" />
</template>
Good
The handlers omit .native and preserve other event modifiers such as .stop.
<template>
<MyComponent @click="handler" />
<MyComponent @click.stop="handler" />
</template>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
vue/no-deprecated-v-on-number-modifiers
Disallow deprecated numeric keyCode modifiers on v-on
Default severity: error
Presets: ecosystem, essential, happy-path, nuxt, opinionated
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/no-deprecated-v-on-number-modifiers": "error"
}
},
},
});
vp run lint
Bad
The keyboard handlers identify keys by the removed numeric codes 13 and 27.
<template>
<input @keyup.13="submit" />
<input v-on:keyup.27="cancel" />
<input @keyup.13.stop="submit" />
</template>
Good
The handlers use the named enter and esc key modifiers.
<template>
<input @keyup.enter="submit" />
<input @keyup.esc="cancel" />
</template>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
vue/no-dupe-v-else-if
Disallow duplicate conditions in v-if / v-else-if chains
Default severity: error
Presets: essential, happy-path, nuxt, ecosystem, opinionated
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/no-dupe-v-else-if": "error"
}
},
},
});
vp run lint
Bad
The else-if repeats the ready condition already tested by the first branch, making that later branch unreachable.
<template>
<p v-if="status === 'ready'">Ready</p>
<p v-else-if="status === 'ready'">Still ready</p>
</template>
Good
The second branch tests loading, a distinct state that can reach the else-if.
<template>
<p v-if="status === 'ready'">Ready</p>
<p v-else-if="status === 'loading'">Loading</p>
</template>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
vue/no-duplicate-attributes
Disallow duplicate attributes on the same element
Default severity: error
Presets: essential, happy-path, nuxt, ecosystem, opinionated
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/no-duplicate-attributes": "error"
}
},
},
});
vp run lint
Bad
The same button declares class twice instead of one combined class value.
<template>
<button class="primary" class="large">Save</button>
</template>
Good
Both class tokens appear in a single class attribute.
<template>
<button class="primary large">Save</button>
</template>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
vue/no-empty-component-block
Disallow empty SFC blocks
Default severity: warning
Presets: nuxt, opinionated
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/no-empty-component-block": "warn"
}
},
},
});
vp run lint
Bad
The template, script, and style blocks contain no meaningful content.
<template></template>
<script></script>
<style>
</style>
Good
Each retained block contains actual markup, script declarations, or style declarations.
<template>
<div>Hello</div>
</template>
<script setup>
const message = "Hello";
</script>
<style scoped>
.button { color: red; }
</style>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
vue/no-inline-style
Discourage use of inline style attributes
Default severity: warning
Presets: nuxt, opinionated
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/no-inline-style": "warn"
}
},
},
});
vp run lint
Bad
The static style attribute embeds the color declaration in the element.
<template>
<div style="color: red">Text</div>
</template>
Good
Classes express the fixed color; the ratio-dependent width remains a dynamic style binding, outside the static-attribute check.
<template>
<div class="text-red">Text</div>
<span :class="{ 'text-red': isRed }">Text</span>
<div :style="{ width: `${ratio}%` }">Text</div>
</template>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
vue/no-invalid-html-attribute
Disallow invalid static values for HTML attributes
Default severity: warning
Presets: happy-path, nuxt, ecosystem, opinionated
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/no-invalid-html-attribute": "warn"
}
},
},
});
vp run lint
Bad
The anchor uses stylesheet as a rel value, although that value belongs to stylesheet link elements.
<template>
<a href="/guide" rel="stylesheet">Guide</a>
</template>
Good
The anchor uses help, a rel value appropriate for a linked help resource.
<template>
<a href="/guide" rel="help">Guide</a>
</template>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
vue/no-lone-template
Disallow unnecessary <template> elements
Default severity: warning
Presets: happy-path, nuxt, ecosystem, opinionated
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/no-lone-template": "warn"
}
},
},
});
vp run lint
Bad
The inner template has no directive or slot role that gives it a structural purpose.
<template>
<div><template><p>Details</p></template></div>
</template>
Good
Removing the unnecessary wrapper leaves the paragraph directly inside div.
<template>
<div><p>Details</p></div>
</template>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
vue/no-multi-spaces
Disallow multiple consecutive spaces
Default severity: warning
Presets: happy-path, nuxt, ecosystem, opinionated
Automatic fix: Available for supported findings
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/no-multi-spaces": "warn"
}
},
},
});
vp run lint
Bad
Two spaces separate attributes or the element name and the first attribute.
<template>
<div class="panel"></div>
<div class="panel" id="main"></div>
</template>
Good
Single spaces separate the same attributes.
<template>
<div class="panel"></div>
<div class="panel" id="main"></div>
</template>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
vue/no-multiple-objects-in-class
Disallow multiple object literals inside a :class array binding
Default severity: warning
Presets: nuxt, opinionated
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/no-multiple-objects-in-class": "warn"
}
},
},
});
vp run lint
Bad
A class array contains two top-level object literals that can be merged.
<template>
<div :class="[{ a }, { b }]"></div>
<div :class="[{ active: isActive }, { error: hasError }]"></div>
</template>
Good
One object contains the class conditions; arrays with one object and a string or with non-literal entries remain allowed.
<template>
<div :class="{ a, b }"></div>
<div :class="[{ active: isActive }, 'static']"></div>
<div :class="[foo, bar]"></div>
</template>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
vue/no-multiple-template-root
Disallow multiple root nodes in a template
Default severity: error
Presets: none
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
Enable only for a single-root contract. Vue 3 normally supports fragments.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/no-multiple-template-root": "error"
}
},
},
});
vp run lint
Bad
The opt-in single-root convention sees two sibling paragraphs at the template root.
<template>
<p>First</p>
<p>Second</p>
</template>
Good
A section wraps the paragraphs into one root; enable this convention only when a single-root contract is intended.
<template>
<section><p>First</p><p>Second</p></section>
</template>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
vue/no-mutating-props
Disallow mutating component props
Default severity: error
Presets: essential, happy-path, nuxt, ecosystem, opinionated
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: See typed options and defaults.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/no-mutating-props": "error"
}
},
},
});
vp run lint
Bad
Incrementing props.count writes directly to a value supplied by the parent.
<script setup lang="ts">
const props = defineProps<{ count: number }>();
props.count++;
</script>
Good
The component emits update:count with the next value, leaving the parent responsible for updating the 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>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
vue/no-negated-v-if-condition
Disallow a negated v-if condition when the chain has a v-else
Default severity: warning
Presets: nuxt, opinionated
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/no-negated-v-if-condition": "warn"
}
},
},
});
vp run lint
Bad
The paired v-if and v-else branches begin with a negated condition.
<template>
<div v-if="!ok">A</div>
<div v-else>B</div>
</template>
Good
A positive ok condition comes first; when inverting a condition, place the original opposite branch first. A lone negated v-if and !== comparisons remain allowed.
<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>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
vue/no-non-component-keep-alive-child
Disallow plain element wrappers directly below <KeepAlive>
Default severity: warning
Presets: none
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/no-non-component-keep-alive-child": "warn"
}
},
},
});
vp run lint
Bad
KeepAlive conditionally wraps a native div rather than directly caching UserCard.
<template>
<KeepAlive>
<div v-if="ready">
<UserCard />
</div>
</KeepAlive>
</template>
Good
The first example makes UserCard the conditional child. The v-show wrapper illustrates a shape outside this conditional-child check, not a promise that the native wrapper is cached.
<template>
<KeepAlive>
<UserCard v-if="ready" />
</KeepAlive>
<KeepAlive>
<div v-show="opened">
<UserCard />
</div>
</KeepAlive>
</template>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
vue/no-preprocessor-lang
Discourage CSS preprocessor usage in favor of modern CSS
Default severity: warning
Presets: nuxt, opinionated
Automatic fix: Not implemented for SFC lint
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
Current support: no-sfc-finding
This catalog entry does not currently emit its rule-specific finding through SFC lint. The Bad/Good pair describes the intended convention, not an executable finding. Enabling the ID does not supply the missing SFC check.
Configured ID (currently no SFC finding)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/no-preprocessor-lang": "warn"
}
},
},
});
vp run lint
Bad
The style block selects SCSS with lang. This describes the intended no-preprocessor convention; the current SFC path does not emit this rule.
<template><p>Notice</p></template>
<style lang="scss">
.notice { color: red; }
</style>
Good
The same CSS declarations omit the preprocessor lang. This is the convention repair, not an executable Bad/Good diagnostic difference today.
<template><p>Notice</p></template>
<style>
.notice { color: red; }
</style>
Good illustrates the intended convention; the current SFC path emits neither side's rule-specific finding.
vue/no-reserved-component-names
Disallow the use of reserved names as component names
Default severity: error
Presets: essential, happy-path, nuxt, ecosystem, opinionated
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/no-reserved-component-names": "error"
}
},
},
});
vp run lint
Bad
The component name button conflicts with a native HTML element name.
<script>
export default {
name: "button",
};
</script>
Good
AppButton is an application component name and does not reuse the native button name.
<script setup lang="ts">
defineOptions({ name: "AppButton" });
</script>
<template>
<Transition>
<AppButton />
</Transition>
</template>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
vue/no-root-v-if
Disallow v-if on the single root element of a template
Default severity: warning
Presets: nuxt, opinionated
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/no-root-v-if": "warn"
}
},
},
});
vp run lint
Bad
The component root itself appears and disappears under v-if.
<template>
<div v-if="show">content</div>
</template>
Good
A stable outer div remains the root while the nested paragraph carries the visibility condition.
<template>
<div>
<p v-if="show">content</p>
</div>
</template>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
vue/no-script-non-standard-lang
Discourage non-standard script lang values
Default severity: warning
Presets: nuxt, opinionated
Automatic fix: Not implemented for SFC lint
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
Current support: no-sfc-finding
This catalog entry does not currently emit its rule-specific finding through SFC lint. The Bad/Good pair describes the intended convention, not an executable finding. Enabling the ID does not supply the missing SFC check.
Configured ID (currently no SFC finding)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/no-script-non-standard-lang": "warn"
}
},
},
});
vp run lint
Bad
The script uses CoffeeScript syntax under lang=coffee. The current SFC path does not emit this catalog rule for that language.
<script lang="coffee">
count = 0
</script>
<template><p>Notice</p></template>
Good
The script uses an ordinary TypeScript declaration with lang=ts, illustrating the intended language convention.
<script lang="ts">
const count = 0;
</script>
<template><p>Notice</p></template>
Good illustrates the intended convention; the current SFC path emits neither side's rule-specific finding.
vue/no-src-attribute
Discourage src attribute on SFC blocks
Default severity: warning
Presets: nuxt, opinionated
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/no-src-attribute": "warn"
}
},
},
});
vp run lint
Bad
The SFC blocks delegate their template, script, and style content to src files.
<template src="./template.html"></template>
<script src="./script.ts"></script>
<style src="./style.css"></style>
Good
Each SFC block contains its own content without an external src attribute.
<template>
<p>Hello</p>
</template>
<script setup lang="ts">
const label = "Hello";
</script>
<style scoped>
p {
color: red;
}
</style>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
vue/no-static-inline-styles
Disallow static inline style attributes
Default severity: warning
Presets: none
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/no-static-inline-styles": "warn"
}
},
},
});
vp run lint
Bad
The paragraph carries the constant color declaration in its style attribute.
<template>
<p style="color: red">Notice</p>
</template>
Good
A notice class and scoped stylesheet hold the constant color outside the template attribute.
<template><p class="notice">Notice</p></template>
<style scoped>.notice { color: red; }</style>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
vue/no-template-key
Disallow key attribute on <template>
Default severity: error
Presets: essential, happy-path, nuxt, ecosystem, opinionated
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/no-template-key": "error"
}
},
},
});
vp run lint
Bad
A non-loop template wrapper has a key even though it is not the keyed iteration boundary.
<template>
<template :key="section"><div>Details</div></template>
</template>
Good
The key belongs to a template v-for iteration, where it identifies each repeated fragment.
<template>
<template v-for="item in items" :key="item.id"><div>{{ item.name }}</div></template>
</template>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
vue/no-template-lang
Discourage lang attribute on template block
Default severity: warning
Presets: nuxt, opinionated
Automatic fix: Not implemented for SFC lint
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
Current support: no-sfc-finding
This catalog entry does not currently emit its rule-specific finding through SFC lint. The Bad/Good pair describes the intended convention, not an executable finding. Enabling the ID does not supply the missing SFC check.
Configured ID (currently no SFC finding)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/no-template-lang": "warn"
}
},
},
});
vp run lint
Bad
The template selects Pug through lang. This is an intended HTML-only convention; the current SFC path does not diagnose this catalog ID.
<template lang="pug">
p Notice
</template>
Good
An ordinary HTML template omits lang and uses the paragraph directly. This illustrates the convention without claiming a current SFC finding.
<template>
<p>Notice</p>
</template>
Good illustrates the intended convention; the current SFC path emits neither side's rule-specific finding.
vue/no-template-shadow
Disallow variable names that shadow variables in outer scope
Default severity: warning
Presets: nuxt, opinionated
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
The current check compares nested v-for bindings. It does not report a single v-for binding merely because it shares a script binding's name.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/no-template-shadow": "warn"
}
},
},
});
vp run lint
Bad
The inner v-for declares item again and hides the outer item binding inside the nested loop.
<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>
Good
The inner loop declares child, leaving item available for the outer row and child for the nested row.
<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>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
vue/no-template-target-blank
Disallow target="_blank" without rel="noopener noreferrer"
Default severity: warning
Presets: happy-path, nuxt, ecosystem, opinionated
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/no-template-target-blank": "warn"
}
},
},
});
vp run lint
Bad
The external link opens a new browsing context without the expected rel protection.
<template>
<a href="https://example.com" target="_blank">x</a>
</template>
Good
The same link includes noopener noreferrer alongside target=_blank.
<template>
<a href="https://example.com" target="_blank" rel="noopener noreferrer">x</a>
</template>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
vue/no-textarea-mustache
Disallow mustache interpolation in <textarea>
Default severity: error
Presets: essential, happy-path, nuxt, ecosystem, opinionated
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/no-textarea-mustache": "error"
}
},
},
});
vp run lint
Bad
The textarea places message in child interpolation instead of binding its value.
<template>
<textarea>{{ message }}</textarea>
</template>
Good
v-model binds the editable textarea value to message.
<template>
<textarea v-model="message"></textarea>
</template>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
vue/no-undefined-refs
Disallow undefined variable references in templates
Default severity: warning
Presets: none
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/no-undefined-refs": "warn"
}
},
},
});
vp run lint
Bad
The template reads missing, although the script declares only message.
<script setup>const message = "Hello";</script>
<template>{{ missing }}</template>
Good
The interpolation reads the existing message binding.
<script setup>const message = "Hello";</script>
<template>{{ message }}</template>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
vue/no-unsafe-url
Warn about potentially unsafe URL bindings
Default severity: warning
Presets: essential, happy-path, nuxt, ecosystem, opinionated
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/no-unsafe-url": "warn"
}
},
},
});
vp run lint
Bad
The anchor destination begins with the executable javascript: scheme.
<template>
<a href="javascript:alert(1)">Continue</a>
</template>
Good
The anchor uses the ordinary local /next navigation destination.
<template>
<a href="/next">Continue</a>
</template>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
vue/no-unsandboxed-iframe
Require a sandbox attribute on iframe elements
Default severity: warning
Presets: happy-path, nuxt, ecosystem, opinionated
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/no-unsandboxed-iframe": "warn"
}
},
},
});
vp run lint
Bad
The embedded frame has no sandbox attribute limiting its capabilities.
<template>
<iframe src="/embed"></iframe>
</template>
Good
sandbox applies restrictions; allow-scripts explicitly opts into that one capability when needed.
<template>
<iframe src="/embed" sandbox></iframe>
<iframe src="/embed" sandbox="allow-scripts"></iframe>
</template>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
vue/no-unused-components
Disallow registering components that are not used inside templates
Default severity: warning
Presets: happy-path, nuxt, ecosystem, opinionated
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/no-unused-components": "warn"
}
},
},
});
vp run lint
Bad
UserAvatar is imported as a component but the template never renders it.
<script setup lang="ts">
import UserAvatar from "./UserAvatar.vue";
</script>
<template>
<p>{{ user.name }}</p>
</template>
Good
The template renders the imported UserAvatar and passes the user binding.
<script setup lang="ts">
import UserAvatar from "./UserAvatar.vue";
</script>
<template>
<UserAvatar :user="user" />
</template>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
vue/no-unused-properties
Disallow unused properties defined in defineProps
Default severity: warning
Presets: happy-path, nuxt, ecosystem, opinionated
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/no-unused-properties": "warn"
}
},
},
});
vp run lint
Bad
The component declares description as a prop but renders only title.
<script setup lang="ts">
defineProps<{ title: string; description: string }>();
</script>
<template>
<h1>{{ title }}</h1>
</template>
Good
Both declared props are referenced by the template.
<script setup lang="ts">
defineProps<{ title: string; description: string }>();
</script>
<template>
<h1>{{ title }}</h1>
<p>{{ description }}</p>
</template>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
vue/no-unused-refs
Report template refs (ref="x") never referenced in <script>
Default severity: warning
Presets: nuxt, opinionated
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/no-unused-refs": "warn"
}
},
},
});
vp run lint
Bad
The template declares the unused ref name with no corresponding script reference binding.
<template><input ref="unused" /></template>
<script setup>
const x = 1
</script>
Good
The inputEl template ref has a same-named ref binding in script setup.
<template><input ref="inputEl" /></template>
<script setup>
import { ref } from 'vue'
const inputEl = ref(null)
</script>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
vue/no-unused-setup-bindings
Disallow unread script setup bindings
Default severity: warning
Presets: none
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/no-unused-setup-bindings": "warn"
}
},
},
});
vp run lint
Bad
The script setup message binding is never read by the template.
<script setup>const message = "Hello";</script>
<template><p>Welcome</p></template>
Good
The paragraph interpolates message, using the declared binding.
<script setup>const message = "Hello";</script>
<template><p>{{ message }}</p></template>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
vue/no-unused-vars
Disallow unused variable definitions in v-for and v-slot directives
Default severity: warning
Presets: essential, happy-path, nuxt, ecosystem, opinionated
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/no-unused-vars": "warn"
}
},
},
});
vp run lint
Bad
The loop declares an unused index and the slot declares foo without referencing it.
<template>
<li v-for="(item, index) in items" :key="item.id">{{ item.name }}</li>
<template v-slot="{ foo }">
<span>Hello</span>
</template>
</template>
Good
The examples consume index or mark it intentionally unused as _index, and the slot renders data. Index keys are only a usage example here, not a recommendation for stable item identity.
<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>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
vue/no-use-v-else-with-v-for
Disallow using v-else-if or v-else on the same element as v-for
Default severity: warning
Presets: none
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/no-use-v-else-with-v-for": "warn"
}
},
},
});
vp run lint
Bad
The else branch and v-for iteration are attached to the same paragraph.
<template>
<p v-if="ready">Ready</p>
<p v-else v-for="item in items" :key="item.id">{{ item.name }}</p>
</template>
Good
A separate template owns v-else, and its child paragraph owns 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>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
vue/no-use-v-if-with-v-for
Disallow using v-if on the same element as v-for
Default severity: warning
Presets: essential, happy-path, nuxt, ecosystem, opinionated
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/no-use-v-if-with-v-for": "warn"
}
},
},
});
vp run lint
Bad
The same list element combines v-if and v-for and tests visibility through the loop binding.
<template>
<li v-for="item in items" v-if="item.visible" :key="item.id">
{{ item.name }}
</li>
</template>
Good
A computed collection filters the visible items before the template iterates over them.
<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>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
vue/no-useless-mustaches
Disallow a mustache interpolation whose expression is a constant string literal
Default severity: warning
Presets: nuxt, opinionated
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/no-useless-mustaches": "warn"
}
},
},
});
vp run lint
Bad
The interpolation contains only a constant string and does not need expression evaluation.
<template>
<div>{{ 'x' }}</div>
<div>{{ "x" }}</div>
<div>{{ `x` }}</div>
</template>
Good
Literal text is written directly; variable expressions, interpolated template strings, and intentional separator whitespace remain interpolation cases.
<template>
<div>x</div>
<div>{{ x }}</div>
<div>{{ `pre-${x}` }}</div>
<span>A</span> {{ " " }} <span>B</span>
</template>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
vue/no-useless-template-attributes
Disallow useless attributes on <template> elements
Default severity: error
Presets: essential, happy-path, nuxt, ecosystem, opinionated
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/no-useless-template-attributes": "error"
}
},
},
});
vp run lint
Bad
The conditional template has a class, but this structural wrapper does not render a DOM element to receive it.
<template>
<section><template v-if="ready" class="notice"><p>Ready</p></template></section>
</template>
Good
The class moves to the paragraph that actually renders while v-if stays on the structural template.
<template>
<section><template v-if="ready"><p class="notice">Ready</p></template></section>
</template>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
vue/no-useless-v-bind
Disallow a v-bind whose value is a plain string literal
Default severity: warning
Presets: nuxt, opinionated
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/no-useless-v-bind": "warn"
}
},
},
});
vp run lint
Bad
The foo binding evaluates a constant quoted string or a template string without interpolation.
<template>
<div :foo="'bar'"></div>
<div :foo="`bar`"></div>
</template>
Good
The constant value becomes a static attribute; variable and interpolated values retain their binding.
<template>
<div foo="bar"></div>
<div :foo="bar"></div>
<div :foo="`pre-${bar}`"></div>
</template>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
vue/no-v-for-template-key-on-child
Disallow key on the child of a <template v-for>
Default severity: error
Presets: essential, happy-path, nuxt, ecosystem, opinionated
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/no-v-for-template-key-on-child": "error"
}
},
},
});
vp run lint
Bad
The child paragraph has the key while the template iteration itself has no key.
<template>
<template v-for="item in items"><p :key="item.id">{{ item.name }}</p></template>
</template>
Good
The key moves to template v-for, identifying the complete repeated fragment.
<template>
<template v-for="item in items" :key="item.id"><p>{{ item.name }}</p></template>
</template>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
vue/no-v-html
Warn against v-html to prevent XSS vulnerabilities
Default severity: warning
Presets: essential, happy-path, nuxt, ecosystem, opinionated
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/no-v-html": "warn"
}
},
},
});
vp run lint
Bad
v-html interprets content as HTML rather than ordinary text.
<template>
<article v-html="content" />
</template>
Good
Mustache interpolation displays content as escaped text instead of injecting HTML.
<template>
<article>{{ content }}</article>
</template>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
vue/no-v-text
Disallow the v-text directive; prefer mustache interpolation
Default severity: warning
Presets: nuxt, opinionated
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/no-v-text": "warn"
}
},
},
});
vp run lint
Bad
The div's content is supplied through the v-text directive.
<template>
<div v-text="message"></div>
</template>
Good
Mustache interpolation expresses the same text binding directly in the element content.
<template>
<div>{{ message }}</div>
</template>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
vue/no-v-text-v-html-on-component
Disallow v-text / v-html on component elements
Default severity: error
Presets: essential, happy-path, nuxt, ecosystem, opinionated
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/no-v-text-v-html-on-component": "error"
}
},
},
});
vp run lint
Bad
The component tag receives v-html or v-text, which replaces element content rather than supplying component slots.
<template>
<MyComponent v-html="content" />
<MyComponent v-text="content" />
</template>
Good
Native HTML targets can receive the directives; MyComponent receives its content through the default slot.
<template>
<div v-html="content"></div>
<component is="div" v-html="content" />
<MyComponent>{{ content }}</MyComponent>
</template>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
vue/permitted-contents
Enforce HTML content model rules
Default severity: error
Presets: happy-path, nuxt, ecosystem, opinionated
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/permitted-contents": "error"
}
},
},
});
vp run lint
Bad
The examples put block content in p, omit the table body, nest interactive controls, or put a div directly inside ul.
<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>
Good
The examples use inline paragraph content, an explicit tbody, and li children. The custom MyItem is not treated as a known native ul child.
<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>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
vue/prefer-props-shorthand
Recommend shorthand syntax for props (Vue 3.4+)
Default severity: warning
Presets: nuxt, opinionated
Automatic fix: Available for supported findings
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/prefer-props-shorthand": "warn"
}
},
},
});
vp run lint
Bad
Each binding repeats the corresponding variable name, including the camelCase equivalent of a hyphenated argument.
<template>
<MyComponent :foo="foo" />
<MyComponent :user-name="userName" />
<span :style="style" />
<div :aria-label="ariaLabel" />
</template>
Good
Vue 3.4+ same-name binding shorthand removes the repeated expressions; a different source variable such as bar remains explicit.
<template>
<MyComponent :foo />
<MyComponent :user-name />
<span :style />
<div :aria-label />
<MyComponent :foo="bar" />
</template>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
vue/prefer-true-attribute-shorthand
Prefer the shorthand for a boolean attribute bound to true
Default severity: warning
Presets: nuxt, opinionated
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/prefer-true-attribute-shorthand": "warn"
}
},
},
});
vp run lint
Bad
A native boolean disabled attribute binds the constant true value.
<template>
<input :disabled="true" />
</template>
Good
The native attribute uses its boolean shorthand. False bindings and component props retain their explicit values.
<template>
<input disabled />
<input :disabled="false" />
<MyComponent :visible="true" />
<MyComponent :visible="isVisible" />
</template>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
vue/prop-name-casing
Enforce a casing for declared prop names
Default severity: warning
Presets: happy-path, nuxt, ecosystem, opinionated
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
Checks declared prop names, not the casing of attributes passed to a child.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/prop-name-casing": "warn"
}
},
},
});
vp run lint
Bad
The declared prop name user_name uses underscore-separated spelling.
<script setup lang="ts">
defineProps<{ user_name: string }>();
</script>
<template><p>{{ user_name }}</p></template>
Good
The declaration and its template reference use the camelCase name userName.
<script setup lang="ts">
defineProps<{ userName: string }>();
</script>
<template><p>{{ userName }}</p></template>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
vue/require-component-is
Require v-bind:is on <component> elements
Default severity: error
Presets: essential, happy-path, nuxt, ecosystem, opinionated
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/require-component-is": "error"
}
},
},
});
vp run lint
Bad
The dynamic <component> has no is target, so Vue cannot choose a component to render.
<template>
<component />
</template>
Good
:is="currentComponent" supplies the component selection; the binding may change at runtime.
<template>
<component :is="currentComponent" />
</template>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
vue/require-component-registration
Require explicit import or registration for components
Default severity: warning
Presets: opinionated
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: See typed options and defaults.
List explicit component names supplied by application plugins or Musea previewSetup. PascalCase and kebab-case spellings are accepted; regular expressions are not interpreted. Options do not enable the rule. Later layers replace the list; an empty list clears inherited names.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/require-component-registration": "warn"
},
"ruleOptions": {
"vue/require-component-registration": {
"globals": [
"MyButton",
"MyIcon"
]
}
}
},
},
});
vp run lint
Bad
MissingWidget is neither registered nor included in the configured global-component allowlist.
<template>
<MissingWidget />
</template>
Good
MyButton is listed in the example's globals option. That option exempts a known global component; it does not register or import it.
<template>
<MyButton />
</template>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
vue/require-scoped-style
Require scoped attribute on style tags
Default severity: warning
Presets: happy-path, nuxt, ecosystem, opinionated
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/require-scoped-style": "warn"
}
},
},
});
vp run lint
Bad
The .button style is unscoped and can affect matching elements outside this component.
<style>
.button {
color: red;
}
</style>
Good
Adding scoped applies Vue's component scope to the same selector and declarations.
<style scoped>
.button {
color: red;
}
</style>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
vue/require-toggle-inside-transition
Require a toggle on the element wrapped by <transition>
Default severity: error
Presets: essential, happy-path, nuxt, ecosystem, opinionated
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/require-toggle-inside-transition": "error"
}
},
},
});
vp run lint
Bad
The static child inside <Transition> has no conditional visibility or dynamic selection to trigger an enter/leave change.
<template>
<transition>
<div>content</div>
</transition>
</template>
Good
v-if="show" changes whether the child exists, giving the transition an enter/leave boundary.
<template>
<transition>
<div v-if="show">content</div>
</transition>
</template>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
vue/require-v-for-key
Require v-bind:key with v-for directives
Default severity: error
Presets: essential, happy-path, nuxt, ecosystem, opinionated
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/require-v-for-key": "error"
}
},
},
});
vp run lint
Bad
Each repeated <li> lacks a key that identifies its corresponding item during list updates.
<template>
<li v-for="item in items">{{ item.name }}</li>
</template>
Good
:key="item.id" gives each repeated node the item's identity rather than its current position.
<template>
<li v-for="item in items" :key="item.id">{{ item.name }}</li>
</template>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
vue/scoped-event-names
Recommend scoped event names using context:event format
Default severity: warning
Presets: nuxt, opinionated
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/scoped-event-names": "warn"
}
},
},
});
vp run lint
Bad
playAudio, pauseAudio, and reloadAudio encode their scope as camel-case suffixes rather than the rule's colon-separated event convention.
<template>
<AudioPlayer
@playAudio="play"
@pauseAudio="pause"
@reloadAudio="reload"
/>
</template>
Good
audio:play, audio:pause, and audio:reload share an explicit audio: scope. The emitting component must use the same names.
<template>
<AudioPlayer
@audio:play="play"
@audio:pause="pause"
@audio:reload="reload"
/>
</template>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
vue/sfc-element-order
Enforce consistent order of SFC top-level elements
Default severity: warning
Presets: happy-path, nuxt, ecosystem, opinionated
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: See typed options and defaults.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/sfc-element-order": "warn"
}
},
},
});
vp run lint
Bad
The style block precedes the script block, contrary to the configured SFC block order.
<style scoped>
.panel {
color: red;
}
</style>
<script setup lang="ts">
const label = "Save";
</script>
Good
The blocks follow script → template → style. Projects can choose a different order through this rule's typed option.
<script setup lang="ts">
const label = "Save";
</script>
<template>
<p>{{ label }}</p>
</template>
<style scoped>
p {
color: red;
}
</style>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
vue/single-style-block
Recommend having a single style block
Default severity: warning
Presets: happy-path, nuxt, ecosystem, opinionated
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/single-style-block": "warn"
}
},
},
});
vp run lint
Bad
The component splits its scoped panel and title styles across two style blocks.
<style scoped>
.panel {
color: red;
}
</style>
<style scoped>
.title {
color: blue;
}
</style>
Good
Both selectors stay scoped in one style block, satisfying the single-block convention without dropping either style.
<style scoped>
.panel {
color: red;
}
.title {
color: blue;
}
</style>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
vue/slot-name-casing
Enforce kebab-case for named slots used via v-slot
Default severity: warning
Presets: nuxt, opinionated
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/slot-name-casing": "warn"
}
},
},
});
vp run lint
Bad
The named slot mySlot uses camelCase where the rule requires a hyphenated name.
<template>
<MyCard><template #mySlot>Content</template></MyCard>
</template>
Good
#my-slot uses kebab-case. Rename the corresponding slot outlet to the same name.
<template>
<MyCard><template #my-slot>Content</template></MyCard>
</template>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
vue/this-in-template
Disallow this. in template expressions
Default severity: warning
Presets: nuxt, opinionated
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/this-in-template": "warn"
}
},
},
});
vp run lint
Bad
Template expressions explicitly access this.message, this.className, and this.handleClick, although Vue exposes those bindings directly.
<template>
<div>{{ this.message }}</div>
<div :class="this.className"></div>
<button @click="this.handleClick()"></button>
</template>
Good
Use message, className, and handleClick directly. The literal string 'this.is.a.string' stays unchanged because it is not a member access.
<template>
<div>{{ message }}</div>
<div :class="className"></div>
<button @click="handleClick()"></button>
<div>{{ 'this.is.a.string' }}</div>
</template>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
vue/use-unique-element-ids
Enforce unique element IDs using useId() instead of static literals
Default severity: warning
Presets: nuxt, opinionated
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/use-unique-element-ids": "warn"
}
},
},
});
vp run lint
Bad
The literal email ID is reused by every instance of this component, which can misdirect its label when several instances are rendered.
<template>
<label for="email">Email</label>
<input id="email" />
</template>
Good
useId() produces the instance's emailId; bind the same value to the label's for and the input's id.
<script setup>
import { useId } from "vue";
const emailId = useId();
</script>
<template>
<label :for="emailId">Email</label>
<input :id="emailId" />
</template>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
vue/use-v-on-exact
Enforce .exact modifier on v-on when there are modifier-based handlers
Default severity: warning
Presets: essential, nuxt, opinionated
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/use-v-on-exact": "warn"
}
},
},
});
vp run lint
Bad
The plain click handler can also run on Ctrl-click, overlapping the separate .ctrl handler.
<template>
<button type="button" @click="handleClick" @click.ctrl="handleCtrlClick">
Save
</button>
</template>
Good
.exact limits the ordinary click handler to clicks without modifier keys; the Ctrl-specific handler remains separate.
<template>
<button
type="button"
@click.exact="handleClick"
@click.ctrl="handleCtrlClick"
>
Save
</button>
</template>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
vue/v-bind-style
Enforce v-bind directive style
Default severity: warning
Presets: nuxt, opinionated
Automatic fix: Available for supported findings
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/v-bind-style": "warn"
}
},
},
});
vp run lint
Bad
v-bind:class uses the long form where the configured binding style requires the colon shorthand.
<template>
<div v-bind:class="panelClass"></div>
</template>
Good
:class retains the same expression with the required shorthand; this rule concerns spelling rather than the value's type.
<template>
<div :class="panelClass"></div>
</template>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
vue/v-on-event-hyphenation
Enforce hyphenation of custom event names in v-on on components
Default severity: warning
Presets: nuxt, opinionated
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: See typed options and defaults.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/v-on-event-hyphenation": "warn"
}
},
},
});
vp run lint
Bad
The custom component listener uses @myEvent instead of a hyphenated event name.
<template>
<MyComponent @myEvent="handler" />
<MyComponent v-on:myEvent="handler" />
</template>
Good
@my-event uses the required custom-event spelling. Native-element listeners and dynamic event arguments shown below are outside this check.
<template>
<MyComponent @my-event="handler" />
<div @myEvent="handler" />
<MyComponent @[dynamicEvent]="handler" />
</template>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
vue/v-on-handler-style
Enforce writing v-on handlers as a method reference or an inline function
Default severity: warning
Presets: nuxt, opinionated
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/v-on-handler-style": "warn"
}
},
},
});
vp run lint
Bad
The handlers put mutations and multiple statements directly in the event attribute.
<template>
<button @click="count++"></button>
<button @click="doThis(); doThat()"></button>
<button @click="foo = bar"></button>
</template>
Good
Use a handler reference, or an arrow/function expression when inline logic is needed. The function boundary makes the handler form explicit.
<template>
<button @click="handler"></button>
<button @click="foo.bar"></button>
<button @click="() => count++"></button>
<button @click="function () { count++ }"></button>
</template>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
vue/v-on-style
Enforce v-on directive style
Default severity: warning
Presets: happy-path, nuxt, ecosystem, opinionated
Automatic fix: Available for supported findings
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/v-on-style": "warn"
}
},
},
});
vp run lint
Bad
v-on:click uses the long event-listener form where the rule requires shorthand.
<template>
<div v-on:click="handleClick"></div>
</template>
Good
@click keeps the same handler while using the configured shorthand.
<template>
<div @click="handleClick"></div>
</template>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
vue/v-slot-style
Enforce v-slot directive style
Default severity: warning
Presets: happy-path, nuxt, ecosystem, opinionated
Automatic fix: Available for supported findings
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/v-slot-style": "warn"
}
},
},
});
vp run lint
Bad
The component uses #default and the template uses v-slot:header, opposite to the rule's context-specific styles.
<template>
<MyComponent #default="props">{{ props.item }}</MyComponent>
<MyComponent>
<template v-slot:header>Header</template>
</MyComponent>
</template>
Good
Use v-slot for the component's default slot and #header for the template's named slot.
<template>
<MyComponent v-slot="props">{{ props.item }}</MyComponent>
<MyComponent>
<template #header>Header</template>
</MyComponent>
</template>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
vue/valid-attribute-name
Require valid attribute names
Default severity: error
Presets: essential, happy-path, nuxt, ecosystem, opinionated
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
Bad diagnostic: parser/template
Malformed attribute spelling is diagnosed by parser/template before this defensive rule sees an attribute. Bad therefore reports parser/template; it does not promise a separate vue/valid-attribute-name finding.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/valid-attribute-name": "error"
}
},
},
});
vp run lint
Bad
The quote inside my"attr makes the attribute name malformed. This example produces the parser's parser/template diagnostic rather than promising a separate rule diagnostic.
<template>
<div my"attr="value"></div>
</template>
Good
my-attr is a well-formed attribute name, so the template parser can read the attribute and its value.
<template>
<div my-attr="value"></div>
</template>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
vue/valid-template-root
Enforce a valid <template> root for Vue 3 fragment semantics
Default severity: error
Presets: essential, happy-path, nuxt, ecosystem, opinionated
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/valid-template-root": "error"
}
},
},
});
vp run lint
Bad
A plain nested <template> occupies the template root without a directive that gives it a rendering role.
<template>
<template>content</template>
</template>
Good
The <div> is a renderable root element. This example does not impose a universal single-root restriction on Vue 3 fragments.
<template>
<div>content</div>
</template>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
vue/valid-v-bind
Enforce valid v-bind directives
Default severity: error
Presets: essential, happy-path, nuxt, ecosystem, opinionated
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/valid-v-bind": "error"
}
},
},
});
vp run lint
Bad
The bare v-bind has no object expression, and the empty argument form has no attribute name.
<template>
<div v-bind></div>
<div :></div>
</template>
Good
Provide an attribute and expression, bind an object, or use Vue 3.4+ same-name shorthand such as :loading.
<template>
<div :class="panelClass"></div>
<div v-bind="{ class: panelClass }"></div>
<div :loading></div>
</template>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
vue/valid-v-cloak
Enforce valid v-cloak directives
Default severity: error
Presets: essential, happy-path, nuxt, ecosystem, opinionated
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/valid-v-cloak": "error"
}
},
},
});
vp run lint
Bad
v-cloak is given a value, argument, or modifier even though it accepts none of those.
<template>
<div v-cloak="foo"></div>
<div v-cloak:arg></div>
<div v-cloak.mod></div>
</template>
Good
Use bare v-cloak; CSS can hide the element until Vue removes that attribute after mounting.
<template>
<div v-cloak></div>
</template>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
vue/valid-v-else
Enforce valid v-else directives
Default severity: error
Presets: essential, happy-path, nuxt, ecosystem, opinionated
Automatic fix: Available for supported findings
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/valid-v-else": "error"
}
},
},
});
vp run lint
Bad
The examples give v-else an expression, combine it with v-if, or omit its adjacent preceding conditional branch.
<template>
<div v-else="ready"></div>
<div v-else v-if="ready"></div>
<div v-else></div>
</template>
Good
Place bare v-else immediately after the corresponding v-if branch.
<template>
<div v-if="ready"></div>
<div v-else></div>
</template>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
vue/valid-v-for
Enforce valid v-for directives
Default severity: error
Presets: essential, happy-path, nuxt, ecosystem, opinionated
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/valid-v-for": "error"
}
},
},
});
vp run lint
Bad
The loops omit their iteration expression or add an unsupported .stop modifier.
<template>
<div v-for></div>
<div v-for=""></div>
<div v-for.stop="item in items"></div>
</template>
Good
Use item in items or (item, index) of items with a complete iteration expression and the shown keys.
<template>
<div v-for="item in items" :key="item.id"></div>
<div v-for="(item, index) of items" :key="index"></div>
</template>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
vue/valid-v-html
Enforce valid v-html directives
Default severity: error
Presets: essential, happy-path, nuxt, ecosystem, opinionated
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/valid-v-html": "error"
}
},
},
});
vp run lint
Bad
v-html lacks its expression or uses an argument/modifier that this directive does not support.
<template>
<div v-html></div>
<div v-html:arg="foo"></div>
<div v-html.mod="foo"></div>
</template>
Good
v-html="html" supplies a valid expression. Syntax validity does not sanitize HTML or make untrusted content safe.
<template>
<div v-html="html"></div>
</template>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
vue/valid-v-if
Enforce valid v-if directives
Default severity: error
Presets: essential, happy-path, nuxt, ecosystem, opinionated
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/valid-v-if": "error"
}
},
},
});
vp run lint
Bad
The conditions omit an expression or combine v-if with an else directive on the same node.
<template>
<div v-if></div>
<div v-if=""></div>
<div v-if="ready" v-else></div>
</template>
Good
Each v-if has a nonempty condition such as ready or count > 0, without an incompatible else directive.
<template>
<div v-if="ready"></div>
<div v-if="count > 0"></div>
</template>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
vue/valid-v-memo
Enforce valid v-memo directives
Default severity: error
Presets: essential, happy-path, nuxt, ecosystem, opinionated
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/valid-v-memo": "error"
}
},
},
});
vp run lint
Bad
Bare v-memo gives Vue no dependency expression for deciding when to reuse the subtree.
<template>
<div v-memo></div>
</template>
Good
v-memo="[valueA, valueB]" supplies the dependency array used for memoization.
<template>
<div v-memo="[valueA, valueB]">{{ label }}</div>
</template>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
vue/valid-v-model
Enforce valid v-model directives
Default severity: error
Presets: essential, happy-path, nuxt, ecosystem, opinionated
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/valid-v-model": "error"
}
},
},
});
vp run lint
Bad
A native <div> cannot use v-model as a form control, and a bare input directive has no writable target expression.
<template>
<div v-model="value"></div>
<input v-model />
</template>
Good
Bind the input, select, textarea, or custom component to the shown writable variables.
<template>
<input v-model="value" />
<select v-model="selected"></select>
<textarea v-model="text"></textarea>
<MyInput v-model="value" />
</template>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
vue/valid-v-on
Enforce valid v-on directives
Default severity: error
Presets: essential, happy-path, nuxt, ecosystem, opinionated
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/valid-v-on": "error"
}
},
},
});
vp run lint
Bad
The listener forms omit an event argument or their required handler/object expression.
<template>
<div v-on></div>
<div @></div>
<div @click></div>
</template>
Good
Use an event with its handler, or pass a listener object to argument-free v-on.
<template>
<div @click="handleClick"></div>
<div v-on="{ click: handleClick }"></div>
</template>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
vue/valid-v-once
Enforce valid v-once directives
Default severity: error
Presets: essential, happy-path, nuxt, ecosystem, opinionated
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/valid-v-once": "error"
}
},
},
});
vp run lint
Bad
v-once has a value, argument, or modifier, although this directive is a value-free render-once marker.
<template>
<div v-once="foo"></div>
<div v-once:arg></div>
<div v-once.mod></div>
</template>
Good
Bare v-once marks the subtree for one-time rendering without unsupported syntax.
<template>
<div v-once></div>
</template>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
vue/valid-v-show
Enforce valid v-show directives
Default severity: error
Presets: essential, happy-path, nuxt, ecosystem, opinionated
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/valid-v-show": "error"
}
},
},
});
vp run lint
Bad
v-show lacks its visibility expression or is placed on a <template> that has no DOM element whose display can be changed.
<template>
<div v-show></div>
<template v-show="ready"><div></div></template>
</template>
Good
Apply the visibility expression to a rendered element such as <div>.
<template>
<div v-show="ready"></div>
<div v-show="count > 0"></div>
</template>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
vue/valid-v-slot
Enforce valid v-slot directives
Default severity: error
Presets: essential, happy-path, nuxt, ecosystem, opinionated
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: See typed options and defaults.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/valid-v-slot": "error"
}
},
},
});
vp run lint
Bad
The slot directive is on a native <div> or conflicts with other default/named slot declarations.
<template>
<div v-slot:header></div>
<MyComponent v-slot v-slot:header />
<template v-slot:header v-slot:footer />
</template>
Good
Declare a component's default slot on that component, or its named slot on a child <template #header>.
<template>
<MyComponent v-slot="{ item }">{{ item }}</MyComponent>
<MyComponent>
<template #header>Header</template>
</MyComponent>
</template>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
vue/valid-v-text
Enforce valid v-text directives
Default severity: error
Presets: essential, happy-path, nuxt, ecosystem, opinionated
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/valid-v-text": "error"
}
},
},
});
vp run lint
Bad
v-text lacks its text expression or uses an unsupported argument/modifier.
<template>
<div v-text></div>
<div v-text:arg="foo"></div>
<div v-text.mod="foo"></div>
</template>
Good
v-text="msg" is syntactically valid. The separate vue/no-v-text style rule can still prefer interpolation.
<template>
<div v-text="msg"></div>
</template>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
vue/warn-custom-block
Warn about custom blocks in SFC files
Default severity: warning
Presets: nuxt, opinionated
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/warn-custom-block": "warn"
}
},
},
});
vp run lint
Bad
The SFC contains an <i18n> custom block, which needs an external integration beyond ordinary template/script/style processing.
<i18n>
{ "en": { "hello": "Hello" } }
</i18n>
<template>
<p>{{ hello }}</p>
</template>
Good
The example uses standard template and script-setup blocks. This optional portability warning does not mean every custom block is invalid Vue.
<template>
<p>{{ hello }}</p>
</template>
<script setup lang="ts">
const hello = "Hello";
</script>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
vue/warn-custom-directive
Warn about custom directives that need registration
Default severity: warning
Presets: nuxt, opinionated
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"vue/warn-custom-directive": "warn"
}
},
},
});
vp run lint
Bad
v-focus, v-mask, and v-click-outside require project-specific directive implementations that this optional convention flags.
<template>
<input v-focus />
<input v-mask="'###-####'" />
<div v-click-outside="handleClose"></div>
</template>
Good
The example uses built-in v-if, v-model, and v-on. A correctly registered custom directive can still be valid Vue when this policy is disabled.
<template>
<div v-if="ready"></div>
<input v-model="value" />
<button type="button" @click="onClick">Save</button>
</template>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.