标签:删除 对象属性 直接 rop 对比 close target 简单的 渲染
基础:vue的响应式规则
父组件
<template> <div> <block-a :out-data="x"></block-a> </div> </template> <script> import blockA from ‘./block-a‘; export default { name: "App", components:{ blockA }, data(){ return { x:123 } }, mounted(){ setTimeout(()=>{ this.x = 789; },1000) } } </script>
子组件
<template> <div> 这是子组件 {{outData}} </div> </template> <script> export default { name: "block-a", props:[‘outData‘], watch:{ outData(newVal){ console.log("新的值是:" + newVal) } } } </script>
运行效果,界面先展示123,一秒后展示789,控制台仅输出了“新的值:789”。
结论:简单的数值类型能通过props动态反映到子组件内,而且能被子组件watch检测。
父组件
<template> <div> <block-a :out-data="x"></block-a> </div> </template> <script> import blockA from ‘./block-a‘; export default { name: "App", components:{ blockA }, data(){ return { x:{ a:123, b:999 } } }, mounted(){ setTimeout(()=>{ this.x.a = 789; },1000) } } </script>
子组件
<template> <div> 这是子组件 {{outData}} </div> </template> <script> export default { name: "block-a", props:[‘outData‘], watch:{ outData(newVal){ console.log("新的值是:" + newVal) } } } </script>
这个例子对比上一个例子,将传递的数据改为了对象类型。对对象属性的变更,能动态反映到子组件中(子组件的界面一秒后发生正确的变化),但watch函数却没有执行(控制台无输出)。
为了监听对象属性的变化,将子组件中的watch设置修改如下:
watch:{
outData:{
handler(newVal){
console.log("新的值是:" + newVal)
},
deep:true
}
}
这样代码运行起来,不仅界面会发生变化,而且控制台也会有输出了(属性变化能被子组件watch检测到了),虽然检测出来有属性变更,却没办法知道到底是哪个属性发生了变更。
补充测试1:修改原有属性,同时添加新的属性(this.x.c=123),则子组件中检测出对象原有属性发生变更后,读取到的对象中也包含了新的属性(c=123)。
补充测试2:父组件中直接为属性赋值一个新的对象,如
setTimeout(()=>{
this.x = {
kkk:123
};
},1000)
则,不管子组件中采用深层watch还是普通的watch检测,都检测出变更(控制台有输出),而且界面也会发生正确变化。
补充测试3:将父组件中的响应式对象删除
<template> <div> <block-a :out-data="x"></block-a> </div> </template> <script> import blockA from ‘./block-a‘; export default { name: "App", components:{ blockA }, data(){ return { } }, mounted(){ setTimeout(()=>{ this.x = { kkk:123 }; },1000) } } </script>
则代码运行会报错,提示渲染期间使用了x,而x未定义。而且后续子组件中没有发生任何变化,控制台也无输出。
结论:当父组件中的响应式对象通过props与子组件中的属性建立了关联后,父组件中的响应式对象发生变更(原属性发生变化和对象被重新赋值,前提是对应的setter存在,这样的赋值才是响应式的),都会通知到被关联子组件去重新渲染(与这个对象相关的属性部分dom渲染),而且watch函数会进入判断(如果是深层watch,则对比对象的属性,如果是普通watch,则简单对应对象的引用),如果没有判断出来发生变化,则不执行watch回调函数。
以上发现一个问题,子组件能监听出对象属性发生了变化,却不知道变化了哪个属性。解决办法是使用简单watch,但是写法得改变一下,要直接定位到我关心的属性上,将子组件的watch修改如下
watch:{
[‘outData.a‘](newVal){
console.log("新的值是:" + newVal)
}
}
对于父组件中的x被重新赋值:新对象不存在a属性或者a属性的值与原来的值不一致时,子组件中的watch才会执行,如果重新赋值后,新对象的a属性与原对象的a属性值相同,则watch回调不执行。
结论:在上一条结论的基础上,多加一点,这个例子中的这种watch写法,仅仅是简单地再次读取对象的某个属性值(a),与原来记录的值进行对比,如果不一致,则执行watch回调。而不在乎外部的对象是否被重新赋值了,还是属性被修改了。
标签:删除 对象属性 直接 rop 对比 close target 简单的 渲染
原文地址:https://www.cnblogs.com/hellohello/p/10217394.html