vue2.0的defineProperty
- 2.0响应式原理在使用中其实理解与否区别不大,但是使用肯定是不但要知其然,也要知其所以然的,简单概述一下2.0的数据响应式原理
1.vue2.0通过Object.defineProperty来劫持对象属性的getter和setter操作(以我的理解大致可以作为说绑定了一个事件,监听事件就是get和set,当数据被改变时,就会触发)
- defineProperty内的参数有以下属性
值 | 释义 |
---|---|
obj | 要定义属性的对象。 |
prop | 要定义或修改的属性的名称或 Symbol 。 |
descriptor | 要定义或修改的属性描述符。 |
- descriptor内的参数也较为简单
属性 | 描述 | 默认值 |
---|---|---|
configurable | 描述符能否被改变 | false |
enumerable | 能否被枚举 | false |
value | 该属性对应的值。 | undefined。 |
writable | 能否被改写 | false |
get | 当访问该属性时调用 | undefined |
set | 当属性值被修改时调用。该方法接受一个被赋予的新值 | undefined |
- observe的极简实现如下
var obj = {};
Object.defineProperty(obj, 'key1', {
//key1在这里实际上就是循环绑定时传入的prop
get: function () {
return val;
},
set: function (newVal) {
val = newVal;
//一般我们用到的也就是此处的set,这个set被触发的时候,就可以在此处进行逻辑
//vue2.0在逻辑中进行了runder函数的触发
}
});
document.addEventListener('keyup', function (e) {
obj.key1= e.target.value;
});
在上述observe函数的实现里,其实还有一个很重要的,就是需要遍历要绑定的数据,递归,
拆分成非对象类型的基础类型来添加劫持
vue3.0的Proxy
Proxy的劫持与2.0使用上实际上区别不大,但是有所
优化及进步
值 | 描述 |
---|---|
target | 要使用 Proxy 包装的目标对象(可以是任何类型的对象,包括原生数组,函数,甚至另一个代理)。 |
handler | 一个通常以函数作为属性的对象,各属性中的函数分别定义了在执行各种操作时代理 p 的行为。 |
- 3.0内的更加简单明了,但是总结在handler内的代理操作更加的完善,很多,十三个拦截方式,想要知道的可以去搜一下Proxy的handler内的能力都有哪些,在我们自己用到及需要了解的其实还是getter和setter操作,升级版的get和set
var obj = {};
var obj1 = new Proxy(obj, {
get: function (target, key, receive) {
return target[key];
},
set: function (target, key, newVal, receive) {
target[key] = newVal;
}
})
document.addEventListener('keyup', function (e) {
obj1[0] = e.target.value;
});
3.0的极简代码与2.0看似没啥区别,但是实际上省略了比较多的步骤,省略了遍历,递归的等步骤,直接劫持对象,Proxy返回一个新对象,可以只操作新对象达到目的,而Object.defineProperty只能遍历对象属性直接修改
修改对象内属性等离谱的操作也变得可以触发set,再也不用深拷贝之类的操作来达到触发更新的目的
- 结尾放一下暴漏弊端的2.0的defineProperty使用代码,助于理解
observe.prototype.observe = function(obj){
var val;
var that = this;
for(let key in obj){//遍历所有属性,依次设置监听
val = obj[key];
if(typeof val ==='object'){
this.observe(val) //如果是对象的话进行递归
}else{
Object.defineProperty(this.$data,key,{
get:function(){
return val;
},
set:function(newVal){
val = newVal;
that.render();
}
})
}
}
}
vue.prototype.render = function(){}//完成渲染的方法
3.0也对vdom的对比进行了升级; 2.0的diff算法会将所有的dom节点依次展开,但是3.0的diff算法会将无需更新数据的节点省略,不会展开和对比节点,这点对性能来说是比较大的优化
关于优化点的动态节点与静态节点的标记有较为成熟的分析可以搜索一下嗷