Vue.js Style Guide
Rule Categories
Priority A: Essential
These rules help prevent errors, so learn and abide by them at all costs. Exceptions may exist, but should be very rare and only be made by those with expert knowledge of both JavaScript and Vue.
Priority B: Strongly Recommended
These rules have been found to improve readability and/or developer experience in most projects. Your code will still run if you violate them, but violations should be rare and well-justified.
Priority A Rules: Essential (Error Prevention)
Multi-word component names
Component names should always be multi-word
, except for root App components, and built-in components provided by Vue, such as <transition>
or <component>
.
This prevents conflictsopen in new window with existing and future HTML elements, since all HTML elements are a single word.
Vue.component("todo-item", {
// ...
});
2
3
export default {
name: "TodoItem",
// ...
};
2
3
4
Component data
Component data
must be a function.
When using the data
property on a component (i.e. anywhere except on new Vue
), the value must be a function that returns an object.
Vue.component("some-comp", {
data: function () {
return {
foo: "bar",
};
},
});
2
3
4
5
6
7
// In a .vue file
export default {
data() {
return {
foo: "bar",
};
},
};
2
3
4
5
6
7
8
Prop definitions
Prop definitions should be as detailed as possible.
In committed code, prop definitions should always be as detailed as possible, specifying at least type(s).
props: {
status: String;
}
2
3
// Even better!
props: {
status: {
type: String,
required: true,
validator: function (value) {
return [
'syncing',
'synced',
'version-conflict',
'error'
].indexOf(value) !== -1
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
v-for
Keyed Always use key
with v-for
.
key
with v-for
is always required on components, in order to maintain internal component state down the subtree.
<ul>
<li v-for="todo in todos" :key="todo.id">{{ todo.text }}</li>
</ul>
2
3
v-if
with v-for
Avoid Never use v-if
on the same element as v-for
.
There are two common cases where this can be tempting:
To filter items in a list (e.g.
v-for="user in users" v-if="user.isActive"
). In these cases, replaceusers
with a new computed property that returns your filtered list (e.g.activeUsers
).To avoid rendering a list if it should be hidden (e.g.
v-for="user in users" v-if="shouldShowUsers"
). In these cases, move thev-if
to a container element (e.g.ul
,ol
).
<ul v-if="shouldShowUsers">
<li v-for="user in users" :key="user.id">{{ user.name }}</li>
</ul>
2
3
Component style scoping
For applications, styles in a top-level App
component and in layout components may be global, but all other components should always be scoped.
<template>
<button class="button button-close">X</button>
</template>
<!-- Использование атрибута `scoped` -->
<style scoped>
.button {
border: none;
border-radius: 2px;
}
.button-close {
background-color: red;
}
</style>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<template>
<button class="c-Button c-Button--close">X</button>
</template>
<!-- Using the BEM convention -->
<style>
.c-Button {
border: none;
border-radius: 2px;
}
.c-Button--close {
background-color: red;
}
</style>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Private property names
Use module scoping to keep private functions inaccessible from the outside. If that’s not possible, always use the $_
prefix for custom private properties in a plugin, mixin, etc that should not be considered public API. Then to avoid conflicts with code by other authors, also include a named scope (e.g. $_yourPluginName_
).
var myGreatMixin = {
// ...
methods: {
$_myGreatMixin_update: function () {
// ...
},
},
};
2
3
4
5
6
7
8
var myGreatMixin = {
// ...
methods: {
publicMethod() {
// ...
myPrivateFunction();
},
},
};
function myPrivateFunction() {
// ...
}
export default myGreatMixin;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Priority B Rules: Strongly Recommended (Improving Readability)
Component files
Whenever a build system is available to concatenate files, each component should be in its own file.
This helps you to more quickly find a component when you need to edit it or review how to use it.
components/
|- TodoList.vue
|- TodoItem.vue
2
3
Single-file component filename casingSTRONGLY RECOMMENDED
Filenames of single-file componentsopen in new window should either be always PascalCase.
PascalCase works best with autocompletion in code editors, as it’s consistent with how we reference components in JS(X) and templates, wherever possible. However, mixed case filenames can sometimes create issues on case-insensitive file systems, which is why kebab-case is also perfectly acceptable.
components/
|- MyComponent.vue
2
Base component names
Base components (a.k.a. presentational, dumb, or pure components) that apply app-specific styling and conventions should all begin with a specific prefix, such as Base
, App
, or V
.
components/
|- BaseButton.vue
|- BaseTable.vue
|- BaseIcon.vue
2
3
4
5
Single-instance component names
Components that should only ever have a single active instance should begin with the The
prefix, to denote that there can be only one.
components/
|- TheHeading.vue
|- TheSidebar.vue
2
3
Tightly coupled component names
Child components that are tightly coupled with their parent should include the parent component name as a prefix.
components/
|- TodoList.vue
|- TodoListItem.vue
|- TodoListItemButton.vue
2
3
4
components/
|- SearchSidebar.vue
|- SearchSidebarNavigation.vue
2
3
Order of words in component names
Component names should start with the highest-level (often most general) words and end with descriptive modifying words.
components/
|- SearchButtonClear.vue
|- SearchButtonRun.vue
|- SearchInputQuery.vue
|- SearchInputExcludeGlob.vue
|- SettingsCheckboxTerms.vue
|- SettingsCheckboxLaunchOnStartup.vue
2
3
4
5
6
7
Self-closing components
<!-- In single-file components, string templates, and JSX -->
<MyComponent />
2
Component name casing in templates
<!-- Everywhere -->
<MyComponent />
2
Full-word component names
Component names should prefer full words over abbreviations.
components/
|- StudentDashboardSettings.vue
|- UserProfileOptions.vue
2
3
Prop name casing
Prop names should always use camelCase during declaration, but kebab-case in templates and JSX.
props: {
greetingText: String;
}
2
3
<WelcomeMessage greeting-text="hi" />
Simple computed properties
Complex computed properties should be split into as many simpler properties as possible.
computed: {
basePrice: function () {
return this.manufactureCost / (1 - this.profitMargin)
},
discount: function () {
return this.basePrice * (this.discountPercent || 0)
},
finalPrice: function () {
return this.basePrice - this.discount
}
}
2
3
4
5
6
7
8
9
10
11
Directive shorthands
Directive shorthands (:
for v-bind:
, @
for v-on:
and #
for v-slot
) should be used always or never.
<input :value="newTodoText" :placeholder="newTodoInstructions" /> ✅
<input v-bind:value="newTodoText" v-bind:placeholder="newTodoInstructions" /> 🚫
2
3
<input @input="onInput" @focus="onFocus" /> ✅
<input v-on:input="onInput" v-on:focus="onFocus" /> 🚫
2
3
<template #header ✅>
<h1>Here might be a page title</h1>
</template>
<template v-slot:header 🚫>
<h1>Here might be a page title</h1>
</template>
2
3
4
5
6
7