Skip to content

Commit

Permalink
Migration guide section on key attribute changes (#481)
Browse files Browse the repository at this point in the history
* feat: add migration guide section about "key" attribute changes
Fix #379

* undo formatting changes in config.js
  • Loading branch information
AjaiKN authored Sep 16, 2020
1 parent 032c9d5 commit 31c7d04
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/.vuepress/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ const sidebar = {
'migration/global-api',
'migration/global-api-treeshaking',
'migration/inline-template-attribute',
'migration/key-attribute',
'migration/keycode-modifiers',
'migration/render-function-api',
'migration/slots-unification',
Expand Down
1 change: 1 addition & 0 deletions src/guide/migration/introduction.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ The following consists a list of breaking changes from 2.x:
- [Custom directive API changed to align with component lifecycle](/guide/migration/custom-directives.html)
- [Some transition classes got a rename](/guide/migration/transition.md)
- [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
- [Changes in `key` attribute usage with `v-if` and `<template v-for>`](/guide/migration/key-attribute.md)
- 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.

### Removed
Expand Down
91 changes: 91 additions & 0 deletions src/guide/migration/key-attribute.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
---
badges:
- breaking
---

# `key` attribute <MigrationBadges :badges="$frontmatter.badges" />

## Overview

- **NEW:** `key`s are no longer necessary on `v-if`/`v-else`/`v-else-if` branches, since Vue now automatically generates unique `key`s.
- **BREAKING:** If you manually provide `key`s, then each branch must use a unique `key`.
- **BREAKING:** `<template v-for>` `key` should be placed on the `<template>` tag (rather than on its children).

## Background

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:

- [List Rendering: Maintaining State](/guide/list.html#maintaining-state)
- [API Reference: `key` Special Attribute](/api/special-attributes.html#key)

## On conditional branches

In Vue 2.x, it was recommended to use `key`s on `v-if`/`v-else`/`v-else-if` branches.

```html
<!-- Vue 2.x -->
<div v-if="condition" key="yes">Yes</div>
<div v-else key="no">No</div>
```

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.

```html
<!-- Vue 3.x -->
<div v-if="condition">Yes</div>
<div v-else>No</div>
```

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.

```html
<!-- Vue 2.x -->
<div v-if="condition" key="a">Yes</div>
<div v-else key="a">No</div>

<!-- Vue 3.x (recommended solution: remove keys) -->
<div v-if="condition">Yes</div>
<div v-else>No</div>

<!-- Vue 3.x (alternate solution: make sure the keys are always unique) -->
<div v-if="condition" key="a">Yes</div>
<div v-else key="b">No</div>
```

## With `<template v-for>`

In Vue 2.x, a `<template>` tag could not have a `key`. Instead, you could place the `key`s on each of its children.

```html
<!-- Vue 2.x -->
<template v-for="item in list">
<div :key="item.id">...</div>
<span :key="item.id">...</span>
</template>
```

In Vue 3.x, the `key` should be placed on the `<template>` tag instead.

```html
<!-- Vue 3.x -->
<template v-for="item in list" :key="item.id">
<div>...</div>
<span>...</span>
</template>
```

Similarly, when using `<template v-for>` with a child that uses `v-if`, the `key` should be moved up to the `<template>` tag.

```html
<!-- Vue 2.x -->
<template v-for="item in list">
<div v-if="item.isVisible" :key="item.id">...</div>
<span v-else :key="item.id">...</span>
</template>

<!-- Vue 3.x -->
<template v-for="item in list" :key="item.id">
<div v-if="item.isVisible">...</div>
<span v-else>...</span>
</template>
```

0 comments on commit 31c7d04

Please sign in to comment.