Skip to content

Commit 31c7d04

Browse files
authored
Migration guide section on key attribute changes (#481)
* feat: add migration guide section about "key" attribute changes Fix #379 * undo formatting changes in config.js
1 parent 032c9d5 commit 31c7d04

File tree

3 files changed

+93
-0
lines changed

3 files changed

+93
-0
lines changed

src/.vuepress/config.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ const sidebar = {
123123
'migration/global-api',
124124
'migration/global-api-treeshaking',
125125
'migration/inline-template-attribute',
126+
'migration/key-attribute',
126127
'migration/keycode-modifiers',
127128
'migration/render-function-api',
128129
'migration/slots-unification',

src/guide/migration/introduction.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ The following consists a list of breaking changes from 2.x:
4242
- [Custom directive API changed to align with component lifecycle](/guide/migration/custom-directives.html)
4343
- [Some transition classes got a rename](/guide/migration/transition.md)
4444
- [Component watch option](/api/options-data.html#watch) and [instance method `$watch`](/api/instance-methods.html#watch) no longer supports dot-delimited string paths, use a computed function as the parameter instead
45+
- [Changes in `key` attribute usage with `v-if` and `<template v-for>`](/guide/migration/key-attribute.md)
4546
- In Vue 2.x, application root container's `outerHTML` is replaced with root component template (or eventually compiled to a template, if root component has no template/render option). Vue 3.x now uses application container's `innerHTML` instead.
4647

4748
### Removed

src/guide/migration/key-attribute.md

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
---
2+
badges:
3+
- breaking
4+
---
5+
6+
# `key` attribute <MigrationBadges :badges="$frontmatter.badges" />
7+
8+
## Overview
9+
10+
- **NEW:** `key`s are no longer necessary on `v-if`/`v-else`/`v-else-if` branches, since Vue now automatically generates unique `key`s.
11+
- **BREAKING:** If you manually provide `key`s, then each branch must use a unique `key`.
12+
- **BREAKING:** `<template v-for>` `key` should be placed on the `<template>` tag (rather than on its children).
13+
14+
## Background
15+
16+
The `key` special attribute is used as a hint for Vue's virtual DOM algorithm to keep track of a node's identity. That way, Vue knows when it can reuse and patch existing nodes and when it needs to reorder or recreate them. For more information, see the following sections:
17+
18+
- [List Rendering: Maintaining State](/guide/list.html#maintaining-state)
19+
- [API Reference: `key` Special Attribute](/api/special-attributes.html#key)
20+
21+
## On conditional branches
22+
23+
In Vue 2.x, it was recommended to use `key`s on `v-if`/`v-else`/`v-else-if` branches.
24+
25+
```html
26+
<!-- Vue 2.x -->
27+
<div v-if="condition" key="yes">Yes</div>
28+
<div v-else key="no">No</div>
29+
```
30+
31+
The example above still works in Vue 3.x. However, we no longer recommend using the `key` attribute on `v-if`/`v-else`/`v-else-if` branches, since unique `key`s are now automatically generated on conditional branches if you don't provide them.
32+
33+
```html
34+
<!-- Vue 3.x -->
35+
<div v-if="condition">Yes</div>
36+
<div v-else>No</div>
37+
```
38+
39+
The breaking change is that if you manually provide `key`s, each branch must use a unique `key`. In most cases, you can remove these `key`s.
40+
41+
```html
42+
<!-- Vue 2.x -->
43+
<div v-if="condition" key="a">Yes</div>
44+
<div v-else key="a">No</div>
45+
46+
<!-- Vue 3.x (recommended solution: remove keys) -->
47+
<div v-if="condition">Yes</div>
48+
<div v-else>No</div>
49+
50+
<!-- Vue 3.x (alternate solution: make sure the keys are always unique) -->
51+
<div v-if="condition" key="a">Yes</div>
52+
<div v-else key="b">No</div>
53+
```
54+
55+
## With `<template v-for>`
56+
57+
In Vue 2.x, a `<template>` tag could not have a `key`. Instead, you could place the `key`s on each of its children.
58+
59+
```html
60+
<!-- Vue 2.x -->
61+
<template v-for="item in list">
62+
<div :key="item.id">...</div>
63+
<span :key="item.id">...</span>
64+
</template>
65+
```
66+
67+
In Vue 3.x, the `key` should be placed on the `<template>` tag instead.
68+
69+
```html
70+
<!-- Vue 3.x -->
71+
<template v-for="item in list" :key="item.id">
72+
<div>...</div>
73+
<span>...</span>
74+
</template>
75+
```
76+
77+
Similarly, when using `<template v-for>` with a child that uses `v-if`, the `key` should be moved up to the `<template>` tag.
78+
79+
```html
80+
<!-- Vue 2.x -->
81+
<template v-for="item in list">
82+
<div v-if="item.isVisible" :key="item.id">...</div>
83+
<span v-else :key="item.id">...</span>
84+
</template>
85+
86+
<!-- Vue 3.x -->
87+
<template v-for="item in list" :key="item.id">
88+
<div v-if="item.isVisible">...</div>
89+
<span v-else>...</span>
90+
</template>
91+
```

0 commit comments

Comments
 (0)