2018.1.17补充说明
纠结的问题终于被解决了
引起这个坑的原因是父组件,父组件foo的数据更新后,模板里调用了foo,导致子组件虚拟节点被 re-render
坑终于被填上了。
之前的内容
标题很绕,我也不知道我在说什么
先来看两个父子组件:
父组件
<template>
<child-component :foo.sync="foo" :bar="[]"/>
</template>
data () {
return {
foo: []
}
}
子组件
<template>
<Button @click="$emit('update:foo', [])">emit</Button>
</template>
props: {
foo: Array,
bar: Array
}
- 子组件接受
foo
、bar
两个props
,类型都是Array
(引用类型) - 子组件通过点击按钮向父组件
emit
事件,给父组件的foo
重新赋值一个空数组 - 父组件bar是通过字面量传值
于是乎,坑爹的地方来了
此时,我们在子组件里watch bar
的变化
watch: {
bar (val) {
console.log(val)
}
}
bar
是父组件通过字面量传入进来的,理论上不会有任何变化,但每点击一次,都会触发watch,控制台会打印bar的值,每次都是一样的空数组
我们修改下父组件,不通过字面量,而是data里显式声明了bar
<template>
<child-component :foo.sync="foo" :bar="bar"/>
</template>
data () {
return {
foo: [],
bar: []
}
}
这时watch没有被触发(计算属性同理)
总结:
- 组件props尽量用值类型
- 引用类型不要用字面量
- props其它的引用类型的改变会触发字面量prop的计算和watch(foo改变了但却触发了bar的重新计算)
- 这算不算是vue的底层bug?
网友评论