前言
本次解析本套高级前端的Vue面试题的第三问,Vue中是如何检测数组变化的,如果对这一问也有所不熟悉的,请一起学习吧。
上一文中,我们提到了Vue2.0和3.0的响应式原理,但是没有深入细讲,在本文会进行深入的分析Vue在2.0版本和3.0版本里,分别是如何检测各种数据类型的值变化,从而做到页面响应式的,并且搞清楚为何数组类型的变化要特殊处理,最后也将Vue从2.x升级到3.x的过程中为何要采用了不同的数据监测原理的原因也一探究竟。
从一段基础代码入手
下面这段代码非常简单,编写过Vue的同学都能看懂它在干什么,但是你能准确的说出这段代码在第一秒,第二秒,第三秒页面上分别有什么变化吗?
<!DOCTYPE html>
<html>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<body>
<div id="app">
<div>{
{ list }}</div>
</div>
<script>
new Vue({
el: '#app',
data: {
list: [],
},
mounted() {
setTimeout(()=>{
this.list[0] = 3
}, 1000)
setTimeout(()=>{
this.list.length = 5
}, 2000)
setTimeout(()=>{
this.$set(this.list, this.list)
}, 3000)
}
})
</script>
</body>
</html>
大家最好能动手拷贝上面的代码,本地新建HTML文件保存后打开调试查看,我这里直接说一下结果。当执行这段代码后,页面在第一秒和第二秒无变化,直到第三秒时候才会发生变化,思考一下第一秒和第二秒改变了list的值,为什么Vue的双向绑定在这里失效了呢?围绕这个问题下面开始一步一步看看Vue的数据变化监听实现机制。
Vue2.0的数据变化监听
这里由浅入深的去看,先从要监听普通数据类型看起。
1、检测属性为基本数据类型
监听普通数据类型,即要监听的对象属性的值为非对象的五种基本类型变化,这里不直接看源码,每一步都自己手动的去实现,更加便于理解。
<!DOCTYPE html>
<html>
<div>
name: <input id="name" />
</div>
</html>
<script>
// 监听Model下的name属性,当name属性有变化时要引起页面id=name的响应变化
const model = {
name: 'vue',
};
// 利用Object.defineProperty创建一个监听器
function observe(obj) {
let val = obj.name;
Object.defineProperty(obj, 'name', {
get() {
return val;
},
set(newVal) {
// 当有新值设置时,执行setter
console.log(`name变化:从${val}到${newVal}`);
// 解析到页面
compile(newVal);
val = newVal;
}
})
}
// 解析器,将变化的数据响应到页面上
function compile(val) {
document.querySelector('#name').value = val;
}
// 调用监听器,对model开始监听
observe(model);
</script>