Vue数据驱动模拟实现2

网友投稿 217 2023-06-19


Vue数据驱动模拟实现2

一、前言

在随笔“模拟vue之数据驱动1”结尾处,我们说到如果监听的属性是个对象呢?那么这个对象中的其他属性岂不就是监听不了了吗?

如下:

倘若user中的name、age属性变化,如何知道它们变化了呢?

今儿,就来解决这一问题。

通过走读Vue源码,发现他是利用Observer构造函数为每个对象创建一个Observer对象,来监听数据的,如果数据中的属性又是一个对象,那么就又通过Observer来监听嘛。

其实,核心思想就是树的先序遍历(关于树,可参考here)。如我们将上述Demo中的data数据,图形化一下,就更加明白了,如下:

好了,理清了大体思路,下面我们就一起来创建一个Observer吧。

二、Observer构造

Observer整体结构如下:

function Observer(data){

//如若this不是Observer对象,即创建一个

if(!(this instanceof Observer)){

return new Observer(data);

}

this.data = data;

this.walk(data);

http://}

let p = Observer.prototype = Object.create(null);

p.walk = function(data){

/*

TODO:监听data数据中的所有属性,

并查看data中属性值是否为对象,

若为对象,就创建一个Observer实例

*/

}

p.convert = function(key, val){

//TODO:通过Object.defineProperty监听数据

}

好了,下面,我们一起来完成walk以及convert方法吧。

-walk-

首先,我们在walk方法中实现对data对象中的所有属性监听,如下:

p.walk = function(data){

let keys = Object.keys(data);

keys.forEach( key => {

let val = data[key];

this.convert(key, val);

});

}

且,由于属性中可能又会是一个对象,那么,我们就有必要监听它们。

怎么办呢?

如果是个对象,再次利用Observer构造函数,处理它不就完了么。

如下:

p.walk = function(data){

let keys = Object.keys(data);

keys.forEach( key => {

let val = data[key];

//如果val为对xAtLxy象,则交给Observer处理

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

Observer(val);

}

this.convert(key, val);

});

}

你可能会有这样的疑问,如果直接利用Observer处理对象,那么不就与父对象失去关联了么?

然而并没有,因为javascript对于对象是指向地址关系,所以怎么会失去关联呢。

-convert-

对于convert方法,就比较简单了,一如既往就是利用Object.defineProperty监听数据,如下:

p.convert = function(key, val){

Object.defineProperty(this.data, key, {

get: ()=>{

console.log('访问了'+key+' 值为'+val);

return val;

},

set: (newVal)=>{

console.log('设置了'+key+' 值为'+newVal);

if(newVal !== val){

val = newVal;

}

}

});

}

好了,到此,一个简单的Observer就构造完成,下面我们就来测试下,是否成功监听了每个属性。

效果如下:

Perfect,完整代码见github。


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

上一篇:ajax的分页查询示例(不刷新页面)
下一篇:vue2滚动条加载更多数据实现代码
相关文章

 发表评论

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