new·The score now tells you which way it movedA brain's exam only ever grows: its own material writes questions, and so does every question a real caller asked and did not get answered. The score is a percentage over that growing set, so a brain that learned more could post a smaller number — and this week three did. One of them answered two MORE questions than the week before and showed eighteen points less. Printed as a single percentage, that reads as decline to a reader and as punishment to anyone who contributes material.all news →
mozg.beta
Sign in

Vue · all subjects

style-guide

37 notes, read out of this brain and free to use. Each one was extracted from a source and is re-checked against its exam.

Style guide rule categories and priority levels

Vue style guide rules are organized into four priority categories. Priority A (Essential) rules prevent errors and must be followed except in rare expert-made exceptions. Priority B (Strongly Recommended) rules improve readability and developer experience; code will run if violated but violations should be rare and justified. Priority C (Recommended) rules apply where multiple equally good options exist and focus on consistency; you can deviate with good reason while maintaining consistency in your codebase. Priority D (Use with Caution) rules identify potentially risky features that should be avoided when overused as they can make code harder to maintain or introduce bugs.

Style guide scope and philosophy

The official Vue style guide provides Vue-specific code recommendations to avoid errors, bikeshedding, and anti-patterns. It is not intended to be ideal for all teams or projects; mindful deviations are encouraged based on past experience, surrounding tech stack, and personal values. The guide focuses on Vue-specific patterns and generally avoids suggestions about JavaScript or HTML in general, such as semicolon usage, trailing commas, or quote styles in HTML attributes.

Multi-word component names required

User component names should always be multi-word, except for root App components. This prevents conflicts with existing and future HTML elements, since all HTML elements are a single word. In pre-compiled templates use PascalCase like TodoItem, and in in-DOM templates use kebab-case like todo-item. Single-word names like Item or item should be avoided.

Detailed prop definitions are essential

In committed code, prop definitions should always be as detailed as possible, specifying at least type(s). Detailed prop definitions have two advantages: they document the API of the component so it is easy to see how the component is meant to be used, and in development Vue will warn if a component is provided incorrectly formatted props, helping catch potential sources of error.

Composition API prop definition examples

Bad example (only OK when prototyping): const props = defineProps(['status']). Good example: const props = defineProps({ status: String }). Even better example with validation: const props = defineProps({ status: { type: String, required: true, validator: (value) => { return ['syncing', 'synced', 'version-conflict', 'error'].includes(value) } } })

Key attribute required with v-for on components

The key attribute with v-for is always required on components in order to maintain internal component state down the subtree. Even for elements, it is a good practice to maintain predictable behavior, such as object constancy in animations.

v-for with key example

Good example: <ul> <li v-for="todo in todos" :key="todo.id" > {{ todo.text }} </li> </ul> Bad example without key: <ul> <li v-for="todo in todos"> {{ todo.text }} </li> </ul>

Never use v-if with v-for on same element

Never use v-if on the same element as v-for. When Vue processes directives, v-if has a higher priority than v-for, which causes the iteration variable to not exist when v-if is evaluated, resulting in an error.

v-if and v-for separation strategies

To filter items in a list, replace the source array with a new computed property that returns the filtered list instead of using v-if on the v-for element. To avoid rendering a list if it should be hidden, move the v-if to a container element like ul or ol. Alternatively, use a template tag with v-for to wrap elements that need conditional rendering.

Composition API computed property for filtered list

Example of filtering with computed property: const activeUsers = computed(() => { return users.filter((user) => user.isActive) })

v-if v-for separation good examples

Good example 1 - using computed property: <ul> <li v-for="user in activeUsers" :key="user.id" > {{ user.name }} </li> </ul> Good example 2 - using template wrapper: <ul> <template v-for="user in users" :key="user.id"> <li v-if="user.isActive"> {{ user.name }} </li> </template> </ul>

Component-scoped styling required

For applications, styles in a top-level App component and in layout components may be global, but all other components should always be scoped. This is only relevant for Single-File Components. Scoping can be achieved through the scoped attribute, CSS modules, a class-based strategy such as BEM, or another library or convention. Component libraries should prefer a class-based strategy instead of using the scoped attribute to make overriding internal styles easier.

Scoped styling with scoped attribute example

Example using the scoped attribute: <template> <button class="button button-close">×</button> </template> <style scoped> .button { border: none; border-radius: 2px; } .button-close { background-color: red; } </style>

CSS modules styling example

Example using CSS modules: <template> <button :class="[$style.button, $style.buttonClose]">×</button> </template> <style module> .button { border: none; border-radius: 2px; } .buttonClose { background-color: red; } </style>

BEM convention styling example

Example using the BEM convention: <template> <button class="c-Button c-Button--close">×</button> </template> <style> .c-Button { border: none; border-radius: 2px; } .c-Button--close { background-color: red; } </style>

Priority A Rules are essential

Priority A Rules help prevent errors and should be learned and abided by 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.

Component/instance options recommended order

Component options should be ordered consistently in this sequence: 1. Global Awareness (name), 2. Template Compiler Options (compilerOptions), 3. Template Dependencies (components, directives), 4. Composition (extends, mixins, provide/inject), 5. Interface (inheritAttrs, props, emits, expose), 6. Composition API (setup), 7. Local State (data, computed), 8. Events (watch, lifecycle events), 9. Non-Reactive Properties (methods), 10. Rendering (template/render).

Lifecycle events order

Lifecycle events should be ordered as follows: beforeCreate, created, beforeMount, mounted, beforeUpdate, updated, activated, deactivated, beforeUnmount, unmounted, errorCaptured, renderTracked, renderTriggered, serverPrefetch (SSR only). These appear in the Events section of component options, specifically under Lifecycle Events.

Element and component attribute order

HTML element and component attributes should be ordered consistently in this sequence: 1. Definition (is), 2. List Rendering (v-for), 3. Conditionals (v-if, v-else-if, v-else, v-show, v-cloak), 4. Render Modifiers (v-pre, v-once), 5. Global Awareness (id), 6. Unique Attributes (ref, key), 7. Two-Way Binding (v-model), 8. Other Attributes (all unspecified bound & unbound attributes), 9. Events (v-on), 10. Content (v-html, v-text).

Empty lines between multi-line properties

You may add one empty line between multi-line properties in component options, particularly if the options cannot fit on screen without scrolling. This is optional and can improve readability and keyboard navigation, as long as the component remains easy to read.

Single-file component top-level element order

Single-file components should order top-level tags consistently, with two acceptable approaches: either <script>, <template>, <style> or <template>, <script>, <style>. The <style> tag should always be last. All components in a codebase should use the same ordering for consistency.

Benefits of following community coding standards

Adapting to community standards provides three benefits: it trains your brain to more easily parse community code, allows you to copy and paste community code examples without modification, and often means new hires are already accustomed to your preferred coding style.

Component files should be separate

Each component should be in its own file whenever a build system is available to concatenate files. This helps you quickly find a component when you need to edit it or review how to use it.

Single-file component filename casing

Filenames of Single-File Components should always be either PascalCase (e.g., MyComponent.vue) or always kebab-case (e.g., my-component.vue). PascalCase works best with autocompletion in code editors and is consistent with how components are referenced in JavaScript and templates. Kebab-case is acceptable for consistency with HTML conventions. Do not use mixed case filenames like myComponent.vue, which can create issues on case-insensitive file systems.

Base component naming convention

Base components (presentational, dumb, or pure components) that apply app-specific styling and conventions should begin with a specific prefix such as Base, App, or V. Examples: BaseButton.vue, BaseTable.vue, BaseIcon.vue or AppButton.vue, AppTable.vue, AppIcon.vue or VButton.vue, VTable.vue, VIcon.vue. These components may only contain HTML elements, other base components, and 3rd-party UI components, but never global state. This convention allows organizing base components alphabetically in editors and simplifies making them global components with Vite.

Tightly coupled component names include parent prefix

Child components that are tightly coupled with their parent should include the parent component name as a prefix. For example, if TodoItem only makes sense in the context of TodoList, name it TodoListItem. Similarly, TodoListItemButton would be a button specific to TodoListItem. This keeps related files alphabetically adjacent in editors. Do not solve this by nesting child components in parent directories, as this results in many files with similar names and many nested sub-directories.

Component name word ordering

Component names should start with the highest-level (often most general) words and end with descriptive modifying words. For example, prefer SearchButtonClear, SearchButtonRun, SearchInputQuery, SearchInputExcludeGlob over ClearSearchButton, RunSearchButton, SearchInput, ExcludeFromSearchInput. This makes important relationships evident at a glance when files are alphabetically organized. Nesting components in directories is not recommended except in very large apps (100+ components) because it takes more time to navigate nested sub-directories.

Self-closing components in different contexts

Components with no content should be self-closing in Single-File Components, string templates, and JSX (e.g., <MyComponent/>), but never in in-DOM templates (use <my-component></my-component> instead). Self-closing syntax communicates that a component has no content and is meant to have no content. This is only possible in Single-File Components and string templates because Vue's compiler can reach the template before the DOM. In-DOM templates must not use self-closing syntax because HTML doesn't allow custom elements to be self-closing.

Component name casing in templates

In most projects, component names should always be PascalCase in Single-File Components and string templates (e.g., <MyComponent/>), but kebab-case in in-DOM templates (e.g., <my-component></my-component>). PascalCase enables editor autocompletion, is more visually distinct from single-word HTML elements, and makes Vue components distinctly visible compared to non-Vue custom elements. In-DOM templates must use kebab-case due to HTML case insensitivity. Alternatively, using kebab-case everywhere is acceptable for consistency across all projects.

Component name casing in JavaScript and JSX

Component names in JavaScript and JSX should always be PascalCase (e.g., import MyComponent from './MyComponent.vue'; app.component('MyComponent', {...}); export default { name: 'MyComponent' }). This follows the JavaScript convention for classes and constructors. However, for applications that use only global component definitions via app.component(), kebab-case inside strings is acceptable (e.g., app.component('my-component', {...})) because global components are rarely referenced in JavaScript and these applications always include many in-DOM templates where kebab-case must be used.

Use full words in component names, avoid abbreviations

Component names should prefer full words over abbreviations. For example, use StudentDashboardSettings instead of SdSettings, and UserProfileOptions instead of UProfOpts. Uncommon abbreviations should always be avoided. The cost of writing longer names is very low due to editor autocompletion, while the clarity gained is invaluable.

Prop name casing rules

Props should always use camelCase during declaration. When used in in-DOM templates, props must be kebab-cased (e.g., <welcome-message greeting-text="hi"></welcome-message>). In Single-File Components and JSX templates, props can use either kebab-case or camelCase (e.g., <WelcomeMessage greeting-text="hi"/> or <WelcomeMessage greetingText="hi"/>). Casing must be consistent throughout the application; do not mix camelCase and kebab-case in the same project. Declaration example: props: { greetingText: String } or const props = defineProps({ greetingText: String })

Multi-attribute elements should span multiple lines

Elements with multiple attributes should span multiple lines with one attribute per line. This applies to templates and JSX. For example: <MyComponent\n foo="a"\n bar="b"\n baz="c"\n/>. Splitting objects with multiple properties over multiple lines is a widely considered good convention in JavaScript and should be applied to templates and JSX as well for improved readability.

Keep template expressions simple

Component templates should only include simple expressions. More complex expressions should be refactored into computed properties or methods. Complex expressions in templates make them less declarative and harder to understand. Templates should describe what should appear, not how the value is computed. Moving complex expressions to computed properties or methods also allows the code to be reused.

Split complex computed properties into simpler ones

Complex computed properties should be split into as many simpler properties as possible. Simpler, well-named computed properties are easier to test (fewer dependencies and simpler expressions), easier to read (descriptive names for each value), and more adaptable to changing requirements (fewer assumptions about how information will be used). For example, instead of a single computed property 'price' that calculates basePrice and applies discount, create three separate computed properties: basePrice, discount, and finalPrice.

Always quote non-empty HTML attribute values

Non-empty HTML attribute values should always be inside quotes (single or double quotes, whichever is not used in JavaScript). Although HTML does not require quotes for attribute values without spaces, avoiding quotes often leads to avoiding spaces in attribute values, making them less readable. For example, use <input type="text"> and <AppSidebar :style="{ width: sidebarWidth + 'px' }"> instead of <input type=text> and <AppSidebar :style={width:sidebarWidth+'px'}>.

Directive shorthands consistency

Directive shorthands should be used always or never throughout a project. The shorthands are: `:` for `v-bind:`, `@` for `v-on:`, and `#` for `v-slot:`. Either consistently use all shorthands (e.g., :value, @input, #header) or consistently use full names (e.g., v-bind:value, v-on:input, v-slot:header) throughout the entire project. Do not mix shorthand and full syntax within the same project.

Give your agent this brain