<!-- item.vue 监听数据 -->
<template>
<div> {{ 'obj' + obj }}、{{ 'id' + id }}、{{ data }} </div>
</template>
<script>
import leftConsoleMixin from '@/mixin/leftConsole'
let key = 1
export default {
name: `item`,
mixins: [leftConsoleMixin],
props: {
obj: Object,
id: [String, Number]
},
data() {
return {
data: key++,
tag: this.$vnode.tag
}
},
watch: {
obj: {
handler(newVal) {
if (newVal) {
console.log(this.tag, 'watch', this.data)
}
},
immediate: true,
deep: true
},
id: {
handler(newVal) {
if (newVal) {
console.log(this.tag, 'watch', this.data)
}
},
immediate: true
}
}
}
</script>
执行操作
- 数组方法和数组下标更改
- 模拟分页情况
- 数组内容不变,下标发生改变
- 叠加2和3
- 深层次的obj对象变更
- 通过set方法变化
测试数据
{
lists: [
{ id: 1, a: 1, b: 1, c: 1 },
{ id: 2, a: 1, b: 1, c: 1 },
{ id: 3, a: 1, b: 1, c: 1 }
],
temp: [
{ id: 1, a: 1, b: 1, c: 1 },
{ id: 2, a: 1, b: 1, c: 1 },
{ id: 3, a: 1, b: 1, c: 1 }
],
deepObj: [{ a: [{ b: [{ d: 1 }], c: 1 }] }]
}
场景一:
key值为index的情况,传的属性为obj
<div>
<item v-for="(obj, index) in lists" :key="index" :obj="obj"/>
</div>
key值为id的情况,传的属性为obj
<div>
<item v-for="obj in lists" :key="obj.id" :obj="obj" />
</div>
lists.splice(0,1)
index时触发1,2组件的watch,删除3
id时删除4
list.reverse()
index时触发1,3watch
id时直接更换位置
key为id时能够准确操作组件 index时则是通过变换传入对值进行复用
场景二:
key值为id的情况,传的属性为基础数据类型id
<div>
<item v-for="{ id } in lists" :key="id" :id="id" />
</div>
key值为index的情况,传的属性为基础数据类型id
<div>
<item v-for="({ id }, index) in lists" :key="index" :id="id" />
</div>
lists.splice(0,1)
index时删除3,更新1,2值
id删除4
lists=temp
引用地址变了,传值不变,不触发更新
场景三:
key值为index的情况,不传的属性
<div>
<item v-for="(obj, index) in lists" :key="index"/>
</div>
key值为id的情况,不传的属性
<div>
<item v-for="obj in lists" :key="obj.id" /></div>
list.reverse()
传入值不变,不触发更新
lists=temp
引用地址变了,传值不变,不触发更新
lists.push(lists.shift())
传入值不变,不触发更新
结论:
- key为唯一值时渲染时会变换组件的位置,而使用index做key时则是改变传入到组件的值
- 传入组件的值没有发生变化时,外层对象的引用地址发生变化,不会触发组件更新