博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
模拟源码深入理解Vue数据驱动原理(2)
阅读量:5911 次
发布时间:2019-06-19

本文共 2571 字,大约阅读时间需要 8 分钟。

  我们说到如果监听的属性是个对象呢?那么这个对象中的其他属性岂不就是监听不了了吗?如下:

  倘若user中的name、age属性变化,如何知道它们变化了呢?今儿,就来解决这一问题。

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

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

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

  Observer整体结构如下:

function Observer(data) {    //如若this不是Observer对象,即创建一个    if (!(this instanceof Observer)) {        return new Observer(data);    }    this.data = data;    this.walk(data);}let p = Observer.prototype = Object.create(null);p.walk = function(data) {    /*    TODO:监听data数据中的所有属性,    并查看data中属性值是否为对象,    若为对象,就创建一个Observer实例    */}p.convert = function(key, val) {    //TODO:通过Object.defineProperty监听数据}

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为对象,则交给Observer处理        if (typeof val === 'object') {            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;            }        }    });}

  完整代码:

function Observer(data) {    //如若this不是Observer对象,即创建一个    if (!(this instanceof Observer)) {        return new Observer(data);    }    this.data = data;    this.walk(data);}let p = Observer.prototype = Object.create(null);p.walk = function(data) {    let keys = Object.keys(data);    keys.forEach(key => {        let val = data[key];        //如果val为对象,则交给Observer处理        if (typeof val === 'object') {            Observer(val);        }        this.convert(key, val);    });}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;            }        }    });}

  使用:

 

转载地址:http://puvpx.baihongyu.com/

你可能感兴趣的文章
POJ2406 Power Strings(KMP)
查看>>
极值问题(acms)
查看>>
SVN Hooks的介绍及使用
查看>>
JAVA核心编程教学
查看>>
apache 限制指定user_agent
查看>>
APP的广告模式
查看>>
判断一个字符是否为数字的两种方法(C/C++)
查看>>
java.util.concurrent.ExecutionException: org.apache.catalina.LifecycleExcept问题解决方案
查看>>
600. Non-negative Integers without Consecutive Ones
查看>>
关于正则表达式的入门心得
查看>>
axios 拦截 , 页面跳转, token 验证(自己摸索了一天搞出来的)
查看>>
区块链初始化与实现POW工作量证明
查看>>
Python从菜鸟到高手(13):分片(Slicing)
查看>>
编码导致 html和aspx 样式差异,变形
查看>>
C++的Json解析库:jsoncpp和boost .
查看>>
如何将经纬度利用Google Map API显示C# VS2005 Sample Code
查看>>
基于html5 canvas和js实现的水果忍者网页版
查看>>
Android 知识梳理
查看>>
【反射】使用反射来获取注解原数据信息-类信息-方法信息等
查看>>
【原创】宿主机远程登录虚拟机(windows server 2003系统)
查看>>