Checking latest version...
A full changelog of past releases is available on [GitHub](https://github.com/vuejs/core/blob/main/CHANGELOG.md).
## Release Cycle {#release-cycle}
Vue does not have a fixed release cycle.
- Patch releases are released as needed.
- Minor releases always contain new features, with a typical time frame of 3~6 months in between. Minor releases always go through a beta pre-release phase.
- Major releases will be announced ahead of time, and will go through an early discussion phase and alpha / beta pre-release phases.
## Semantic Versioning Edge Cases {#semantic-versioning-edge-cases}
Vue releases follow [Semantic Versioning](https://semver.org/) with a few edge cases.
### TypeScript Definitions {#typescript-definitions}
We may ship incompatible changes to TypeScript definitions between **minor** versions. This is because:
1. Sometimes TypeScript itself ships incompatible changes between minor versions, and we may have to adjust types to support newer versions of TypeScript.
2. Occasionally we may need to adopt features that are only available in a newer version of TypeScript, raising the minimum required version of TypeScript.
If you are using TypeScript, you can use a semver range that locks the current minor and manually upgrade when a new minor version of Vue is released.
### Compiled Code Compatibility with Older Runtime {#compiled-code-compatibility-with-older-runtime}
A newer **minor** version of Vue compiler may generate code that isn't compatible with the Vue runtime from an older minor version. For example, code generated by Vue 3.2 compiler may not be fully compatible if consumed by the runtime from Vue 3.1.
This is only a concern for library authors, because in applications, the compiler version and the runtime version is always the same. A version mismatch can only happen if you ship pre-compiled Vue component code as a package, and a consumer uses it in a project using an older version of Vue. As a result, your package may need to explicitly declare a minimum required minor version of Vue.
## Pre Releases {#pre-releases}
Minor releases typically go through a non-fixed number of beta releases. Major releases will go through an alpha phase and a beta phase.
Additionally, we publish canary releases every week from the `main` and `minor` branches on GitHub. They are published as different packages to avoid bloating the npm metadata of the stable channel. You can install them via `npx install-vue@canary` or `npx install-vue@canary-minor`, respectively.
Pre-releases are meant for integration / stability testing, and for early adopters to provide feedback for unstable features. Do not use pre-releases in production. All pre-releases are considered unstable and may ship breaking changes in between, so always pin to exact versions when using pre-releases.
## Deprecations {#deprecations}
We may periodically deprecate features that have new, better replacements in minor releases. Deprecated features will continue to work, and will be removed in the next major release after it entered deprecated status.
## RFCs {#rfcs}
New features with substantial API surface and major changes to Vue will go through the **Request for Comments** (RFC) process. The RFC process is intended to provide a consistent and controlled path for new features to enter the framework, and give the users an opportunity to participate and offer feedback in the design process.
The RFC process is conducted in the [vuejs/rfcs](https://github.com/vuejs/rfcs) repo on GitHub.
## Experimental Features {#experimental-features}
Some features are shipped and documented in a stable version of Vue, but marked as experimental. Experimental features are typically features that have an associated RFC discussion with most of the design problems resolved on paper, but still lacking feedback from real-world usage.
The goal of experimental features is to allow users to provide feedback for them by testing them in a production setting, without having to use an unstable version of Vue. Experimental features themselves are considered unstable, and should only be used in a controlled manner, with the expectation that the feature may change between any release types.
---
# Source: https://vuejs.org/guide/extras/render-function.md
# Source: https://vuejs.org/api/render-function.md
---
url: /api/render-function.md
---
# Render Function APIs {#render-function-apis}
## h() {#h}
Creates virtual DOM nodes (vnodes).
- **Type**
```ts
// full signature
function h(
type: string | Component,
props?: object | null,
children?: Children | Slot | Slots
): VNode
// omitting props
function h(type: string | Component, children?: Children | Slot): VNode
type Children = string | number | boolean | VNode | null | Children[]
type Slot = () => Children
type Slots = { [name: string]: Slot }
```
> Types are simplified for readability.
- **Details**
The first argument can either be a string (for native elements) or a Vue component definition. The second argument is the props to be passed, and the third argument is the children.
When creating a component vnode, the children must be passed as slot functions. A single slot function can be passed if the component expects only the default slot. Otherwise, the slots must be passed as an object of slot functions.
For convenience, the props argument can be omitted when the children is not a slots object.
- **Example**
Creating native elements:
```js
import { h } from 'vue'
// all arguments except the type are optional
h('div')
h('div', { id: 'foo' })
// both attributes and properties can be used in props
// Vue automatically picks the right way to assign it
h('div', { class: 'bar', innerHTML: 'hello' })
// class and style have the same object / array
// value support like in templates
h('div', { class: [foo, { bar }], style: { color: 'red' } })
// event listeners should be passed as onXxx
h('div', { onClick: () => {} })
// children can be a string
h('div', { id: 'foo' }, 'hello')
// props can be omitted when there are no props
h('div', 'hello')
h('div', [h('span', 'hello')])
// children array can contain mixed vnodes and strings
h('div', ['hello', h('span', 'hello')])
```
Creating components:
```js
import Foo from './Foo.vue'
// passing props
h(Foo, {
// equivalent of some-prop="hello"
someProp: 'hello',
// equivalent of @update="() => {}"
onUpdate: () => {}
})
// passing single default slot
h(Foo, () => 'default slot')
// passing named slots
// notice the `null` is required to avoid
// slots object being treated as props
h(MyComponent, null, {
default: () => 'default slot',
foo: () => h('div', 'foo'),
bar: () => [h('span', 'one'), h('span', 'two')]
})
```
- **See also** [Guide - Render Functions - Creating VNodes](/guide/extras/render-function#creating-vnodes)
## mergeProps() {#mergeprops}
Merge multiple props objects with special handling for certain props.
- **Type**
```ts
function mergeProps(...args: object[]): object
```
- **Details**
`mergeProps()` supports merging multiple props objects with special handling for the following props:
- `class`
- `style`
- `onXxx` event listeners - multiple listeners with the same name will be merged into an array.
If you do not need the merge behavior and want simple overwrites, native object spread can be used instead.
- **Example**
```js
import { mergeProps } from 'vue'
const one = {
class: 'foo',
onClick: handlerA
}
const two = {
class: { bar: true },
onClick: handlerB
}
const merged = mergeProps(one, two)
/**
{
class: 'foo bar',
onClick: [handlerA, handlerB]
}
*/
```
## cloneVNode() {#clonevnode}
Clones a vnode.
- **Type**
```ts
function cloneVNode(vnode: VNode, extraProps?: object): VNode
```
- **Details**
Returns a cloned vnode, optionally with extra props to merge with the original.
Vnodes should be considered immutable once created, and you should not mutate the props of an existing vnode. Instead, clone it with different / extra props.
Vnodes have special internal properties, so cloning them is not as simple as an object spread. `cloneVNode()` handles most of the internal logic.
- **Example**
```js
import { h, cloneVNode } from 'vue'
const original = h('div')
const cloned = cloneVNode(original, { id: 'foo' })
```
## isVNode() {#isvnode}
Checks if a value is a vnode.
- **Type**
```ts
function isVNode(value: unknown): boolean
```
## resolveComponent() {#resolvecomponent}
For manually resolving a registered component by name.
- **Type**
```ts
function resolveComponent(name: string): Component | string
```
- **Details**
**Note: you do not need this if you can import the component directly.**
`resolveComponent()` must be called inside
```js
import { h, resolveComponent } from 'vue'
export default {
setup() {
const ButtonCounter = resolveComponent('ButtonCounter')
return () => {
return h(ButtonCounter)
}
}
}
```
```js
import { h, resolveComponent } from 'vue'
export default {
render() {
const ButtonCounter = resolveComponent('ButtonCounter')
return h(ButtonCounter)
}
}
```
- **See also** [Guide - Render Functions - Components](/guide/extras/render-function#components)
## resolveDirective() {#resolvedirective}
For manually resolving a registered directive by name.
- **Type**
```ts
function resolveDirective(name: string): Directive | undefined
```
- **Details**
**Note: you do not need this if you can import the directive directly.**
`resolveDirective()` must be called inside` element. It contains all the information that we need to create the actual element. It also contains more children vnodes, which makes it the root of a virtual DOM tree.
A runtime renderer can walk a virtual DOM tree and construct a real DOM tree from it. This process is called **mount**.
If we have two copies of virtual DOM trees, the renderer can also walk and compare the two trees, figuring out the differences, and apply those changes to the actual DOM. This process is called **patch**, also known as "diffing" or "reconciliation".
The main benefit of virtual DOM is that it gives the developer the ability to programmatically create, inspect and compose desired UI structures in a declarative way, while leaving the direct DOM manipulation to the renderer.
## Render Pipeline {#render-pipeline}
At the high level, this is what happens when a Vue component is mounted:
1. **Compile**: Vue templates are compiled into **render functions**: functions that return virtual DOM trees. This step can be done either ahead-of-time via a build step, or on-the-fly by using the runtime compiler.
2. **Mount**: The runtime renderer invokes the render functions, walks the returned virtual DOM tree, and creates actual DOM nodes based on it. This step is performed as a [reactive effect](./reactivity-in-depth), so it keeps track of all reactive dependencies that were used.
3. **Patch**: When a dependency used during mount changes, the effect re-runs. This time, a new, updated Virtual DOM tree is created. The runtime renderer walks the new tree, compares it with the old one, and applies necessary updates to the actual DOM.

## Templates vs. Render Functions {#templates-vs-render-functions}
Vue templates are compiled into virtual DOM render functions. Vue also provides APIs that allow us to skip the template compilation step and directly author render functions. Render functions are more flexible than templates when dealing with highly dynamic logic, because you can work with vnodes using the full power of JavaScript.
So why does Vue recommend templates by default? There are a number of reasons:
1. Templates are closer to actual HTML. This makes it easier to reuse existing HTML snippets, apply accessibility best practices, style with CSS, and for designers to understand and modify.
2. Templates are easier to statically analyze due to their more deterministic syntax. This allows Vue's template compiler to apply many compile-time optimizations to improve the performance of the virtual DOM (which we will discuss below).
In practice, templates are sufficient for most use cases in applications. Render functions are typically only used in reusable components that need to deal with highly dynamic rendering logic. Render function usage is discussed in more detail in [Render Functions & JSX](./render-function).
## Compiler-Informed Virtual DOM {#compiler-informed-virtual-dom}
The virtual DOM implementation in React and most other virtual-DOM implementations are purely runtime: the reconciliation algorithm cannot make any assumptions about the incoming virtual DOM tree, so it has to fully traverse the tree and diff the props of every vnode in order to ensure correctness. In addition, even if a part of the tree never changes, new vnodes are always created for them on each re-render, resulting in unnecessary memory pressure. This is one of the most criticized aspect of virtual DOM: the somewhat brute-force reconciliation process sacrifices efficiency in return for declarativeness and correctness.
But it doesn't have to be that way. In Vue, the framework controls both the compiler and the runtime. This allows us to implement many compile-time optimizations that only a tightly-coupled renderer can take advantage of. The compiler can statically analyze the template and leave hints in the generated code so that the runtime can take shortcuts whenever possible. At the same time, we still preserve the capability for the user to drop down to the render function layer for more direct control in edge cases. We call this hybrid approach **Compiler-Informed Virtual DOM**.
Below, we will discuss a few major optimizations done by the Vue template compiler to improve the virtual DOM's runtime performance.
### Cache Static {#cache-static}
Quite often there will be parts in a template that do not contain any dynamic bindings:
```vue-html{2-3}
```
[Inspect in Template Explorer](https://template-explorer.vuejs.org/#eyJzcmMiOiI8ZGl2PlxuICA8ZGl2PmZvbzwvZGl2PiA8IS0tIGNhY2hlZCAtLT5cbiAgPGRpdj5iYXI8L2Rpdj4gPCEtLSBjYWNoZWQgLS0+XG4gIDxkaXY+e3sgZHluYW1pYyB9fTwvZGl2PlxuPC9kaXY+XG4iLCJvcHRpb25zIjp7ImhvaXN0U3RhdGljIjp0cnVlfX0=)
The `foo` and `bar` divs are static - re-creating vnodes and diffing them on each re-render is unnecessary. The renderer creates these vnodes during the initial render, caches them, and reuses the same vnodes for every subsequent re-render. The renderer is also able to completely skip diffing them when it notices the old vnode and the new vnode are the same one.
In addition, when there are enough consecutive static elements, they will be condensed into a single "static vnode" that contains the plain HTML string for all these nodes ([Example](https://template-explorer.vuejs.org/#eyJzcmMiOiI8ZGl2PlxuICA8ZGl2IGNsYXNzPVwiZm9vXCI+Zm9vPC9kaXY+XG4gIDxkaXYgY2xhc3M9XCJmb29cIj5mb288L2Rpdj5cbiAgPGRpdiBjbGFzcz1cImZvb1wiPmZvbzwvZGl2PlxuICA8ZGl2IGNsYXNzPVwiZm9vXCI+Zm9vPC9kaXY+XG4gIDxkaXYgY2xhc3M9XCJmb29cIj5mb288L2Rpdj5cbiAgPGRpdj57eyBkeW5hbWljIH19PC9kaXY+XG48L2Rpdj4iLCJzc3IiOmZhbHNlLCJvcHRpb25zIjp7ImhvaXN0U3RhdGljIjp0cnVlfX0=)). These static vnodes are mounted by directly setting `innerHTML`.
### Patch Flags {#patch-flags}
For a single element with dynamic bindings, we can also infer a lot of information from it at compile time:
```vue-html
{{ dynamic }}
```
[Inspect in Template Explorer](https://template-explorer.vuejs.org/#eyJzcmMiOiI8ZGl2IDpjbGFzcz1cInsgYWN0aXZlIH1cIj48L2Rpdj5cblxuPGlucHV0IDppZD1cImlkXCIgOnZhbHVlPVwidmFsdWVcIj5cblxuPGRpdj57eyBkeW5hbWljIH19PC9kaXY+Iiwib3B0aW9ucyI6e319)
When generating the render function code for these elements, Vue encodes the type of update each of them needs directly in the vnode creation call:
```js{3}
createElementVNode("div", {
class: _normalizeClass({ active: _ctx.active })
}, null, 2 /* CLASS */)
```
The last argument, `2`, is a [patch flag](https://github.com/vuejs/core/blob/main/packages/shared/src/patchFlags.ts). An element can have multiple patch flags, which will be merged into a single number. The runtime renderer can then check against the flags using [bitwise operations](https://en.wikipedia.org/wiki/Bitwise_operation) to determine whether it needs to do certain work:
```js
if (vnode.patchFlag & PatchFlags.CLASS /* 2 */) {
// update the element's class
}
```
Bitwise checks are extremely fast. With the patch flags, Vue is able to do the least amount of work necessary when updating elements with dynamic bindings.
Vue also encodes the type of children a vnode has. For example, a template that has multiple root nodes is represented as a fragment. In most cases, we know for sure that the order of these root nodes will never change, so this information can also be provided to the runtime as a patch flag:
```js{4}
export function render() {
return (_openBlock(), _createElementBlock(_Fragment, null, [
/* children */
], 64 /* STABLE_FRAGMENT */))
}
```
The runtime can thus completely skip child-order reconciliation for the root fragment.
### Tree Flattening {#tree-flattening}
Taking another look at the generated code from the previous example, you'll notice the root of the returned virtual DOM tree is created using a special `createElementBlock()` call:
```js{2}
export function render() {
return (_openBlock(), _createElementBlock(_Fragment, null, [
/* children */
], 64 /* STABLE_FRAGMENT */))
}
```
Conceptually, a "block" is a part of the template that has stable inner structure. In this case, the entire template has a single block because it does not contain any structural directives like `v-if` and `v-for`.
Each block tracks any descendant nodes (not just direct children) that have patch flags. For example:
```vue-html{3,5}
```
The result is a flattened array that contains only the dynamic descendant nodes:
```
div (block root)
- div with :id binding
- div with {{ bar }} binding
```
When this component needs to re-render, it only needs to traverse the flattened tree instead of the full tree. This is called **Tree Flattening**, and it greatly reduces the number of nodes that need to be traversed during virtual DOM reconciliation. Any static parts of the template are effectively skipped.
`v-if` and `v-for` directives will create new block nodes:
```vue-html
```
A child block is tracked inside the parent block's array of dynamic descendants. This retains a stable structure for the parent block.
### Impact on SSR Hydration {#impact-on-ssr-hydration}
Both patch flags and tree flattening also greatly improve Vue's [SSR Hydration](/guide/scaling-up/ssr#client-hydration) performance:
- Single element hydration can take fast paths based on the corresponding vnode's patch flag.
- Only block nodes and their dynamic descendants need to be traversed during hydration, effectively achieving partial hydration at the template level.
---
# Source: https://vuejs.org/guide/scaling-up/routing.md
---
url: /guide/scaling-up/routing.md
---
# Routing {#routing}
## Client-Side vs. Server-Side Routing {#client-side-vs-server-side-routing}
Routing on the server side means the server is sending a response based on the URL path that the user is visiting. When we click on a link in a traditional server-rendered web app, the browser receives an HTML response from the server and reloads the entire page with the new HTML.
In a [Single-Page Application](https://developer.mozilla.org/en-US/docs/Glossary/SPA) (SPA), however, the client-side JavaScript can intercept the navigation, dynamically fetch new data, and update the current page without full page reloads. This typically results in a more snappy user experience, especially for use cases that are more like actual "applications", where the user is expected to perform many interactions over a long period of time.
In such SPAs, the "routing" is done on the client side, in the browser. A client-side router is responsible for managing the application's rendered view using browser APIs such as [History API](https://developer.mozilla.org/en-US/docs/Web/API/History) or the [`hashchange` event](https://developer.mozilla.org/en-US/docs/Web/API/Window/hashchange_event).
## Official Router {#official-router}
Watch a Free Video Course on Vue School
Vue is well-suited for building SPAs. For most SPAs, it's recommended to use the officially-supported [Vue Router library](https://github.com/vuejs/router). For more details, see Vue Router's [documentation](https://router.vuejs.org/).
## Simple Routing from Scratch {#simple-routing-from-scratch}
If you only need very simple routing and do not wish to involve a full-featured router library, you can do so with [Dynamic Components](/guide/essentials/component-basics#dynamic-components) and update the current component state by listening to browser [`hashchange` events](https://developer.mozilla.org/en-US/docs/Web/API/Window/hashchange_event) or using the [History API](https://developer.mozilla.org/en-US/docs/Web/API/History).
Here's a bare-bone example:
```vue
Home |
About |
Broken Link
```
[Try it in the Playground](https://play.vuejs.org/#eNptUk1vgkAQ/SsTegAThZp4MmhikzY9mKanXkoPWxjLRpgly6JN1P/eWb5Eywlm572ZN2/m5GyKwj9U6CydsIy1LAyUaKpiHZHMC6UNnEDjbgqxyovKYAIX2GmVg8sktwe9qhzbdz+wga15TW++VWX6fB3dAt6UeVEVJT2me2hhEcWKSgOamVjCCk4RAbiBu6xbT5tI2ML8VDeI6HLlxZXWSOZdmJTJPJB3lJSoo5+pWBipyE9FmU4soU2IJHk+MGUrS4OE2nMtIk4F/aA7BW8Cq3WjYlDbP4isQu4wVp0F1Q1uFH1IPDK+c9cb1NW8B03tyJ//uvhlJmP05hM4n60TX/bb2db0CoNmpbxMDgzmRSYMcgQQCkjZhlXkPASRs7YmhoFYw/k+WXvKiNrTcQgpmuFv7ZOZFSyQ4U9a7ZFgK2lvSTXFDqmIQbCUJTMHFkQOBAwKg16kM3W6O7K3eSs+nbeK+eee1V/XKK0dY4Q3vLhR6uJxMUK8/AFKaB6k)
```vue
Home |
About |
Broken Link
```
[Try it in the Playground](https://play.vuejs.org/#eNptUstO6zAQ/ZVR7iKtVJKLxCpKK3Gli1ggxIoNZmGSKbFoxpEzoUi0/87YeVBKNonHPmfOmcdndN00yXuHURblbeFMwxtFpm6sY7i1NcLW2RriJPWBB8bT8/WL7Xh6D9FPwL3lG9tROWHGiwGmqLDUMjhhYgtr+FQEEKdxFqRXfaR9YrkKAoqOnocfQaDEre523PNKzXqx7M8ADrlzNEYAReccEj9orjLYGyrtPtnZQrOxlFS6rXqgZJdPUC5s3YivMhuTDCkeDe6/dSalvognrkybnIgl7c4UuLhcwuHgS3v2/7EPvzRruRXJ7/SDU12W/98l451pGQndIvaWi0rTK8YrEPx64ymKFQOce5DOzlfs4cdlkA+NzdNpBSRgrJudZpQIINdQOdyuVfQnVdHGzydP9QYO549hXIII45qHkKUL/Ail8EUjBgX+z9k3JLgz9OZJgeInYElAkJlWmCcDUBGkAsrTyWS0isYV9bv803x1OTiWwzlrWtxZ2lDGDO90mWepV3+vZojHL3QQKQE=)
---
# Source: https://vuejs.org/style-guide/rules-essential.md
---
url: /style-guide/rules-essential.md
---
# Priority A Rules: Essential {#priority-a-rules-essential}
::: warning Note
This Vue.js Style Guide is outdated and needs to be reviewed. If you have any questions or suggestions, please [open an issue](https://github.com/vuejs/docs/issues/new).
:::
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.
## Use multi-word component names {#use-multi-word-component-names}
User component names should always be multi-word, except for root `App` components. This [prevents conflicts](https://html.spec.whatwg.org/multipage/custom-elements.html#valid-custom-element-name) with existing and future HTML elements, since all HTML elements are a single word.
Bad
```vue-html
```
Good
```vue-html
```
## Use detailed prop definitions {#use-detailed-prop-definitions}
In committed code, prop definitions should always be as detailed as possible, specifying at least type(s).
::: details Detailed Explanation
Detailed [prop definitions](/guide/components/props#prop-validation) have two advantages:
- They document the API of the component, so that it's easy to see how the component is meant to be used.
- In development, Vue will warn you if a component is ever provided incorrectly formatted props, helping you catch potential sources of error.
:::
Bad
```js
// This is only OK when prototyping
props: ['status']
```
Good
```js
props: {
status: String
}
```
```js
// Even better!
props: {
status: {
type: String,
required: true,
validator: value => {
return [
'syncing',
'synced',
'version-conflict',
'error'
].includes(value)
}
}
}
```
Bad
```js
// This is only OK when prototyping
const props = defineProps(['status'])
```
Good
```js
const props = defineProps({
status: String
})
```
```js
// Even better!
const props = defineProps({
status: {
type: String,
required: true,
validator: (value) => {
return ['syncing', 'synced', 'version-conflict', 'error'].includes(
value
)
}
}
})
```
## Use keyed `v-for` {#use-keyed-v-for}
`key` with `v-for` is _always_ required on components, in order to maintain internal component state down the subtree. Even for elements though, it's a good practice to maintain predictable behavior, such as [object constancy](https://bost.ocks.org/mike/constancy/) in animations.
::: details Detailed Explanation
Let's say you have a list of todos:
```js
data() {
return {
todos: [
{
id: 1,
text: 'Learn to use v-for'
},
{
id: 2,
text: 'Learn to use key'
}
]
}
}
```
```js
const todos = ref([
{
id: 1,
text: 'Learn to use v-for'
},
{
id: 2,
text: 'Learn to use key'
}
])
```
Then you sort them alphabetically. When updating the DOM, Vue will optimize rendering to perform the cheapest DOM mutations possible. That might mean deleting the first todo element, then adding it again at the end of the list.
The problem is, there are cases where it's important not to delete elements that will remain in the DOM. For example, you may want to use `
` to animate list sorting, or maintain focus if the rendered element is an ` `. In these cases, adding a unique key for each item (e.g. `:key="todo.id"`) will tell Vue how to behave more predictably.
In our experience, it's better to _always_ add a unique key, so that you and your team simply never have to worry about these edge cases. Then in the rare, performance-critical scenarios where object constancy isn't necessary, you can make a conscious exception.
:::
## Avoid `v-if` with `v-for` {#avoid-v-if-with-v-for}
**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, replace `users` 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 the `v-if` to a container element (e.g. `ul`, `ol`).
::: details Detailed Explanation
When Vue processes directives, `v-if` has a higher priority than `v-for`, so that this template:
```vue-html
```
Will throw an error, because the `v-if` directive will be evaluated first and the iteration variable `user` does not exist at this moment.
This could be fixed by iterating over a computed property instead, like this:
```js
computed: {
activeUsers() {
return this.users.filter(user => user.isActive)
}
}
```
```js
const activeUsers = computed(() => {
return users.filter((user) => user.isActive)
})
```
```vue-html
```
Alternatively, we can use a `` tag with `v-for` to wrap the `` element:
```vue-html
```
:::
Good
```vue-html
```
```vue-html
```
## Use component-scoped styling {#use-component-scoped-styling}
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](/guide/scaling-up/sfc). It does _not_ require that the [`scoped` attribute](https://vue-loader.vuejs.org/guide/scoped-css.html) be used. Scoping could be through [CSS modules](https://vue-loader.vuejs.org/guide/css-modules.html), a class-based strategy such as [BEM](http://getbem.com/), or another library/convention.
**Component libraries, however, should prefer a class-based strategy instead of using the `scoped` attribute.**
This makes overriding internal styles easier, with human-readable class names that don't have too high specificity, but are still very unlikely to result in a conflict.
::: details Detailed Explanation
If you are developing a large project, working with other developers, or sometimes include 3rd-party HTML/CSS (e.g. from Auth0), consistent scoping will ensure that your styles only apply to the components they are meant for.
Beyond the `scoped` attribute, using unique class names can help ensure that 3rd-party CSS does not apply to your own HTML. For example, many projects use the `button`, `btn`, or `icon` class names, so even if not using a strategy such as BEM, adding an app-specific and/or component-specific prefix (e.g. `ButtonClose-icon`) can provide some protection.
:::
Bad
```vue-html
×
```
Good
```vue-html
×
```
```vue-html
×
```
```vue-html
×
```
---
# Source: https://vuejs.org/style-guide/rules-recommended.md
---
url: /style-guide/rules-recommended.md
---
# Priority C Rules: Recommended {#priority-c-rules-recommended}
::: warning Note
This Vue.js Style Guide is outdated and needs to be reviewed. If you have any questions or suggestions, please [open an issue](https://github.com/vuejs/docs/issues/new).
:::
Where multiple, equally good options exist, an arbitrary choice can be made to ensure consistency. In these rules, we describe each acceptable option and suggest a default choice. That means you can feel free to make a different choice in your own codebase, as long as you're consistent and have a good reason. Please do have a good reason though! By adapting to the community standard, you will:
1. Train your brain to more easily parse most of the community code you encounter
2. Be able to copy and paste most community code examples without modification
3. Often find new hires are already accustomed to your preferred coding style, at least in regards to Vue
## Component/instance options order {#component-instance-options-order}
**Component/instance options should be ordered consistently.**
This is the default order we recommend for component options. They're split into categories, so you'll know where to add new properties from plugins.
1. **Global Awareness** (requires knowledge beyond the component)
- `name`
2. **Template Compiler Options** (changes the way templates are compiled)
- `compilerOptions`
3. **Template Dependencies** (assets used in the template)
- `components`
- `directives`
4. **Composition** (merges properties into the options)
- `extends`
- `mixins`
- `provide`/`inject`
5. **Interface** (the interface to the component)
- `inheritAttrs`
- `props`
- `emits`
6. **Composition API** (the entry point for using the Composition API)
- `setup`
7. **Local State** (local reactive properties)
- `data`
- `computed`
8. **Events** (callbacks triggered by reactive events)
- `watch`
- Lifecycle Events (in the order they are called)
- `beforeCreate`
- `created`
- `beforeMount`
- `mounted`
- `beforeUpdate`
- `updated`
- `activated`
- `deactivated`
- `beforeUnmount`
- `unmounted`
- `errorCaptured`
- `renderTracked`
- `renderTriggered`
9. **Non-Reactive Properties** (instance properties independent of the reactivity system)
- `methods`
10. **Rendering** (the declarative description of the component output)
- `template`/`render`
## Element attribute order {#element-attribute-order}
**The attributes of elements (including components) should be ordered consistently.**
This is the default order we recommend for component options. They're split into categories, so you'll know where to add custom attributes and directives.
1. **Definition** (provides the component options)
- `is`
2. **List Rendering** (creates multiple variations of the same element)
- `v-for`
3. **Conditionals** (whether the element is rendered/shown)
- `v-if`
- `v-else-if`
- `v-else`
- `v-show`
- `v-cloak`
4. **Render Modifiers** (changes the way the element renders)
- `v-pre`
- `v-once`
5. **Global Awareness** (requires knowledge beyond the component)
- `id`
6. **Unique Attributes** (attributes that require unique values)
- `ref`
- `key`
7. **Two-Way Binding** (combining binding and events)
- `v-model`
8. **Other Attributes** (all unspecified bound & unbound attributes)
9. **Events** (component event listeners)
- `v-on`
10. **Content** (overrides the content of the element)
- `v-html`
- `v-text`
## Empty lines in component/instance options {#empty-lines-in-component-instance-options}
**You may want to add one empty line between multi-line properties, particularly if the options can no longer fit on your screen without scrolling.**
When components begin to feel cramped or difficult to read, adding spaces between multi-line properties can make them easier to skim again. In some editors, such as Vim, formatting options like this can also make them easier to navigate with the keyboard.
Bad
```js
props: {
value: {
type: String,
required: true
},
focused: {
type: Boolean,
default: false
},
label: String,
icon: String
},
computed: {
formattedValue() {
// ...
},
inputClasses() {
// ...
}
}
```
Good
```js
// No spaces are also fine, as long as the component
// is still easy to read and navigate.
props: {
value: {
type: String,
required: true
},
focused: {
type: Boolean,
default: false
},
label: String,
icon: String
},
computed: {
formattedValue() {
// ...
},
inputClasses() {
// ...
}
}
```
Bad
```js
defineProps({
value: {
type: String,
required: true
},
focused: {
type: Boolean,
default: false
},
label: String,
icon: String
})
const formattedValue = computed(() => {
// ...
})
const inputClasses = computed(() => {
// ...
})
```
Good
```js
defineProps({
value: {
type: String,
required: true
},
focused: {
type: Boolean,
default: false
},
label: String,
icon: String
})
const formattedValue = computed(() => {
// ...
})
const inputClasses = computed(() => {
// ...
})
```
## Single-file component top-level element order {#single-file-component-top-level-element-order}
**[Single-File Components](/guide/scaling-up/sfc) should always order `
...
```
```vue-html [ComponentA.vue]
...
```
```vue-html [ComponentB.vue]
...
```