面试题答案
一键面试key 属性的作用
- 高效更新虚拟 DOM:Vue 在更新 DOM 时,会对比新旧虚拟 DOM 树。当节点处于 Fragment 中时,key 作为节点的唯一标识,能帮助 Vue 快速识别哪些节点发生了变化,哪些节点需要更新、添加或删除。避免不必要的 DOM 操作,从而提升渲染性能。例如,在一个列表渲染的 Fragment 中,如果没有 key,Vue 可能会复用错误的 DOM 元素,导致显示异常。
- 组件状态管理:对于包含在 Fragment 中的组件,key 可以影响组件的创建和销毁。当 key 变化时,Vue 会重新创建组件实例,而不是复用之前的实例。这在一些需要重置组件状态的场景下非常有用。
正确设置 key 提升渲染性能的方法
- 使用唯一且稳定的值:在列表渲染场景中,最好使用数据项中具有唯一性的标识作为 key。例如,如果列表是用户列表,每个用户有唯一的
id
,那么使用id
作为 key 是最佳选择。如:
<template>
<Fragment>
<div v-for="user in users" :key="user.id">
{{ user.name }}
</div>
</Fragment>
</template>
<script>
export default {
data() {
return {
users: [
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' }
]
};
}
};
</script>
- 避免使用索引作为 key:虽然使用索引作为 key 看似简单,但在列表发生增删改操作时,会导致 Vue 做出错误的 DOM 操作判断。例如:
<template>
<Fragment>
<div v-for="(user, index) in users" :key="index">
{{ user.name }}
</div>
</Fragment>
</template>
<script>
export default {
data() {
return {
users: [
{ name: 'Alice' },
{ name: 'Bob' }
]
};
},
methods: {
addUser() {
this.users.unshift({ name: 'Charlie' });
}
}
};
</script>
当调用 addUser
方法时,由于 key 是索引,Vue 会认为原来索引为 0 的 Alice
变成了 Charlie
,索引为 1 的 Bob
变成了 Alice
,从而错误地复用 DOM 元素,导致性能问题和显示异常。
不同 key 设置带来的渲染差异
- 使用唯一标识作为 key:假设我们有一个任务列表,任务有唯一
taskId
。
<template>
<Fragment>
<div v-for="task in tasks" :key="task.taskId">
{{ task.title }}
</div>
</Fragment>
</template>
<script>
export default {
data() {
return {
tasks: [
{ taskId: 1, title: 'Task 1' },
{ taskId: 2, title: 'Task 2' }
]
};
},
methods: {
updateTask() {
this.tasks[0].title = 'Updated Task 1';
}
}
};
</script>
当调用 updateTask
方法时,Vue 能准确识别出是 taskId
为 1 的任务发生了变化,仅更新对应的 DOM 元素,渲染高效且准确。
- 使用索引作为 key:同样是上述任务列表,若使用索引作为 key:
<template>
<Fragment>
<div v-for="(task, index) in tasks" :key="index">
{{ task.title }}
</div>
</Fragment>
</template>
<script>
export default {
data() {
return {
tasks: [
{ title: 'Task 1' },
{ title: 'Task 2' }
]
};
},
methods: {
addTask() {
this.tasks.unshift({ title: 'New Task' });
}
}
};
</script>
当调用 addTask
方法时,Vue 会错误地认为所有任务的位置都发生了变化,对所有 DOM 元素进行更新,而不是仅添加新的 DOM 元素,导致不必要的性能开销。