问题描述
Vue中当子组件使用watch监听父组件的Date类型的属性的值的变化的时候,会出现修改了父组件中与Date类型属性不相干的属性的值的时候仍旧触发了Date类型的属性的监听事件,如下面的示例会发现当调用了父组件的changeOther方法修改了order的值的时候,子模块的watch中的date监听执行了,即使是date的值未发生改变。
父模块:
<template>
<div>
....
<child :date="new Date(date)"></child>
<div>
</template>
import child from ./Child.vue
export default{
components:{
child
},
data(){
return{
other:[],
date:'2023-11-29',
}
},
method:{
changeOther(){
this.other=[]
}
}
}
子模块:
<template>
<div>
...
<div>
</template>
export default{
props:{
date:{
type:Date,
}
},
watch:{
date(){
console.log('触发了date修改事件')
}
}
}
原因分析:
在 Vue 中,当父模块更新一个数组变量的值时,会触发子组件的重新渲染。这是因为子组件依赖于父组件传递的数组数据。当数组数据发生变化时,Vue 会自动检测到这一变化并更新子组件的视图。
因为子组件在处理数组数据变化的同时,也对 date 变量进行了监听。当数组数据发生变化时,子组件的 watch 方法会被触发,从而执行相应的逻辑。
这里的父组件中传值的时候使用了<child :date="new Date(date)"></child>,其中new Date导致了传给子组件的date的值看着是一样的,但是其实又不是一样的。
根本原因还是JavaScript中的Date类型不能直接比较不同。如果需要比较两个日期,需要先将它们转换为相同的时间戳(毫秒数),然后再进行比较
解决方案:
修改子组件
<template>
<div>
...
<div>
</template>
export default{
props:{
date:{
type:Date,
}
},
watch:{
date:{
handler(newTime,oldTime){
if(newTime==undefined) return;
if(oldTime == undefined){
console.log('触发了date修改事件');
return;
}
const newSpan = newTime.getTime();
const oldSpan = oldTime.getTime();
if(newSpan !== oldSpan){
console.log('触发了date修改事件');
}
},
deep:true,
immediate:true
}
}
}