Vue数据驱动模拟实现3

网友投稿 186 2023-06-19


Vue数据驱动模拟实现3

一、前言

在"模拟vue之数据驱动2"中,我们实现了个Observer构造函数,通过它可以达到监听已有数据data中的所有属性。

但,倘若我们想在某个对象中,新增某个属性呢?

如下:

那么岂不是,新增的infor属性,以及它的对象属性,没有得到监听。

此时,应该怎么处理呢?

通过走读Vue源码,发现他是采用另增属性方法$set实现的。

就是说,如果我们采用常规方法为对象增加属性(如上),我们没法得知并监控它,所以,我们为每个对象扩展一个$set方法,用于另增属性使用,即可,如下:

data.user.$set('infor', {msg: 'happy'});

好了,下面,我们就一同实现这个$set方法吧。

二、$set方法实现

首先,我们得创建一个恒定extendObj对象,用于将$set方法绑定在其中。

你可能会想,为什么我们需要一个extendObj对象呢?直接将$set函数赋值给每个需要监听的对象不就完了么?

是的,这样也可以,但是随着需求增长,倘若我们又想为每个监听对象扩展其他方法呢?难道又要去Observer里面为对象,一一赋值?

so,创建恒定extendObj对象,如下:

const extendObj = {};

因为,我们将$set绑定到extendObj中,且让$set为不可枚举型,所以会用到Object.defineProperty,固将其提取出来,作为一个方法如下:

function proxyObject(obj, key, val, enume){

Object.defineProperty(obj, key, {

value: val,

enumerable: !!enume,

writable: true,

configurable: true

});

};

接下来,就是实现$set方法了,整体结构如下:

proxyObject(extendObj, '$set', function(key, val){

//this指向extendObj

if(this.hasOwnProperty(key)){

return;

}else{

/*

TODO:在extendObj中监听key属性,

且,若key属性值为对象,再次监听key属性值

*/

}

});

看到上面的TODO注释,是否似曾相识,不就是是在“模拟Vue之数据驱动2”遇见过的嘛,通过Observer.prototype.convert监听key属性,通过new Observer再次监听key属性值不就完啦。

的确,但是一旦这样做了,不就和上面我们提到的“直接将$set赋予监听对象”问题一样嘛,耦合性太大,且随着需求上涨,不易维护。

固而,在此需要一点小技巧:在observer模块中为每个监听对象赋予一个$Observer属性,其值指向Observer自身实例,如下:

//observer.js

p.walk = function(data){

let keys = Object.keys(data);

keys.forEach( key => {

let val = data[key];

if(typeof val === 'object'){

new Observer(val);

}

this.convert(key, val);

});

//$Observer属性指向Observer自身实例

data.$Observer = this;

}

//新增一个observe方法

p.observe = function(data){

if(typeof data === 'object'){

new Observer(data);

}

}

好了,这样之后,得$set整体实现如下:

proxyObject(extendObj, '$set', function(key, val){

if(this.hasOwnProperty(key)){

return;

}else{

proxyObject(this, key, val, true);

let ob = this.$Observer;

ob.observe(val);

ob.convert(key, val);

}

});

到此,一个简单的$set方法构建完毕。

在上面我们提到,之所以需要一个恒定extendObj对象,是为了更好的代码管理。且,到目前为止,需要监听的对象上并没有扩展Fdzuei$set方法呢,所以,下面的事情就是为了达到以上效果,如下:

//observer.js

function Observer(data){

if(!(this instanceof Observer)){

return new Observer(data);

}

//将监听对象的隐指针指向我们的extendObj对象

data.__proto__ = extendObj;

this.data = data;

this.walk(data);

}

好了,一切完毕,接下来就测试下吧:

效果如下:

Perfect,完整代码见github。


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:Java中线程死亡的几种情况实例分析
下一篇:Java图片裁剪和生成缩略图的实例方法
相关文章

 发表评论

暂时没有评论,来抢沙发吧~