vue基础进阶(七):key的作用

271 阅读3分钟

key值的作用

1 用 key 管理可复用的元素(一个页面同时用两个相同组件的个例)

Vue 会尽可能高效地渲染元素,通常会复用已有元素而不是从头开始渲染。这么做除了使 Vue 变得非常快之外,还有其它一些好处。例如,如果你允许用户在不同的登录方式之间切换:

<template v-if="loginType === 'username'">
  <label>Username</label>
  <input placeholder="Enter your username">
</template>
<template v-else>
  <label>Email</label>
  <input placeholder="Enter your email address">
</template>

那么在上面的代码中切换 loginType 将不会清除用户已经输入的内容。因为两个模板使用了相同的元素, 不会被替换掉——仅仅是替换了它的 placeholder。 自己动手试一试,在输入框中输入一些文本,然后按下切换按钮: 这样也不总是符合实际需求,所以 Vue 为你提供了一种方式来表达“这两个元素是完全独立的,不要复用它们”。只需添加一个具有唯一值的 key 属性即可:

<template v-if="loginType === 'username'">
  <label>Username</label>
  <input placeholder="Enter your username" key="username-input">
</template>
<template v-else>
  <label>Email</label>
  <input placeholder="Enter your email address" key="email-input">
</template>

现在,每次切换时,输入框都将被重新渲染。请看: 注意, 元素仍然会被高效地复用,因为它们没有添加 key 属性。

2 在v-for中:维护状态

当 Vue 正在更新使用 v-for 渲染的元素列表时,它默认使用“就地更新”的策略。如果数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序,而是就地更新每个元素,并且确保它们在每个索引位置正确渲染,这个默认的模式是高效的,但是只适用于不依赖子组件状态或临时 DOM 状态 (例如:表单输入值) 的列表渲染输出。有相同父元素的子元素必须有独特的 key。重复的 key 会造成渲染错误。

举例说明:

<div id="app">
    <div v-for="i in dataList">{{ i }}</div>
</div>

var vm = new Vue({
  el: '#app',
  data: {
    dataList: [1, 2, 3, 4, 5]
  }
})

以上的例子,v-for的内容会生成以下的dom节点数组,我们给每一个节点标记一个身份id:

 [
    '<div>1</div>', // id: A
    '<div>2</div>', // id:  B
    '<div>3</div>', // id:  C
    '<div>4</div>', // id:  D
    '<div>5</div>'  // id:  E
  ]

改变dataList数据,进行数据位置替换,对比改变后的数据

 vm.dataList = [4, 1, 3, 5, 2] // 数据位置替换

// 没有key的情况, 节点位置不变,但是节点innerText内容更新了
[
  '<div>4</div>', // id: A
  '<div>1</div>', // id:  B
  '<div>3</div>', // id:  C
  '<div>5</div>', // id:  D
  '<div>2</div>'  // id:  E
]

// 有key的情况,dom节点位置进行了交换,但是内容没有更新
// <div v-for="i in dataList" :key='i'>{{ i }}</div>
[
  '<div>4</div>', // id: D
  '<div>1</div>', // id:  A
  '<div>3</div>', // id:  C
  '<div>5</div>', // id:  E
  '<div>2</div>'  // id:  B
]

增删dataList列表项

 vm.dataList = [3, 4, 5, 6, 7] // 数据进行增删

// 1. 没有key的情况, 节点位置不变,内容也更新了
[
  '<div>3</div>', // id: A
  '<div>4</div>', // id:  B
  '<div>5</div>', // id:  C
  '<div>6</div>', // id:  D
  '<div>7</div>'  // id:  E
]

// 2. 有key的情况, 节点删除了 A, B 节点,新增了 F, G 节点
// <div v-for="i in dataList" :key='i'>{{ i }}</div>
[
  '<div>3</div>', // id: C
  '<div>4</div>', // id:  D
  '<div>5</div>', // id:  E
  '<div>6</div>', // id:  F
  '<div>7</div>'  // id:  G
]