面试题答案
一键面试Vue对复杂对象及其嵌套属性变化监听的原理
Vue 使用 Object.defineProperty()
方法来进行数据劫持,为对象的每个属性定义 getter 和 setter。对于嵌套对象,Vue 会递归地将其所有属性都进行数据劫持。在 Vue 2.x 中,由于 JavaScript 的限制,对于对象新增属性或删除属性,Vue 无法自动监听,需要使用 Vue.set
或 $set
方法来触发响应式更新。对于数组,Vue 重写了数组的原型方法(如 push
、pop
、shift
、unshift
、splice
、sort
、reverse
),当调用这些方法时会触发视图更新。
代码展示精确监听 'hobbies' 数组变化
<template>
<div>
<button @click="addHobby">添加爱好</button>
<button @click="changeHobbyOrder">改变爱好顺序</button>
</div>
</template>
<script>
export default {
data() {
return {
data: {
person: {
name: 'John',
age: 30,
hobbies: ['reading', 'traveling']
}
}
};
},
watch: {
'data.person.hobbies': {
handler(newVal, oldVal) {
console.log('hobbies 数组变化了', newVal, oldVal);
},
deep: true
}
},
methods: {
addHobby() {
this.data.person.hobbies.push('coding');
},
changeHobbyOrder() {
this.data.person.hobbies.reverse();
}
}
};
</script>
在上述代码中,通过在 watch
中设置 deep: true
来深度监听 hobbies
数组的变化,这样即使数组内部元素顺序改变也能监听到。handler
函数中的 newVal
和 oldVal
分别代表变化后的数组和变化前的数组。