vue响应式原理及依赖收集的介绍 (附代码)


本文摘自PHP中文网,作者不言,侵删。

本篇文章给大家带来的内容是关于vue响应式原理及依赖收集的介绍 (附代码),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。

Vue通过设定对象属性的setter/getter方法来监听数据的变化,通过getter进行依赖收集,而每个setter方法就是一个观察者,在数据变更的时候通知订阅者更新视图。

将数据data变成可观察的(observable)

那么Vue是如何将所有data下面的属性变成可观察的呢?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

function obsever(value,cb){

    Object.keys(value).forEach((key)=>defineReactive(value,key,value[key],cb))

}

function defineReactive(obj,key,val,cb){

    Object.defineProperty(obj,key,{

        enumerable;true,

        configurable:true,

        get:()=>{

            /*依赖收集*/

            return val;

        },

        set:newVal=>{

            val=newVal;

            cb();

        }

    })

}

class Vue{

    constructor(options){

        this._data = options.data;

        obsever(this._data,options.render)

    }

}

 

let app = new Vue({

    el:'#app',

    data:{

        text:'text',

        text2:'text2'

    },

    render(){

        console.log('render')

    }

})

为了便于理解,首先考虑一种最简单的情况,不考虑数组等情况,代码如上所示。在initData中会调用observe这个函数将Vue的数据设置成observable的。当_data数据发生改变的时候就会触发set,对订阅者进行回调(在这里是render)。
那么问题来了,需要对app._data.text操作才会触发set。为了偷懒,我们需要一种方便的方法通过app.text直接设置就能触发set对视图进行重绘。那么就需要到代理。

代理

我们可以在Vue的构造函数constructor中为data执行一个代理proxy。这样我们就把data上面的属性代理到了vm实例上。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

_proxy.call(this,options.data);//构造函数

//代理

function _proxy(data){

    const that = this;

    Object.keys(data).forEach(key=>{

        configurable:true,

        enumerable:true,

        get:function proxyGetter(){

            return that._data[key]

        },

        set:function proxySetter(val){

            that._data[key] = val;

        }

    })

}

我们就可以用app.text代替app._data.text了。

为什么要依赖收集

先看下面这段代码

1

2

3

4

5

6

7

8

9

10

11

new Vue({

    template:`<p>

                <span>text1:</span>{{text1}}

                <span>text2:</span>{{tetx2}}

              </p>`,

    data:{

        text1:'text1',

        text2:'text2',

        text3:'text3'

    }

})

按照上面的响应式原理中的方法进行绑定则会出现一个问题--text3在实际模板中并没有被用到,然而当text3的数据被修改时,同样会触发text3的setter导致重新执行渲染,这显然不正确。

先说说Dep

当对data上的对象进行修改值的时候会触发它的setter,那么取值的时候自然会触发getter事件,所以我们只要在最开始进行一次render,那么所有被渲染所依赖的data中的数据就会被getter收集到Dep的subs中去。在对data中的数据进行修改的时候setter只会触发Dep的subs函数。
定义一个依赖收集类的Dep。

阅读剩余部分

相关阅读 >>

javascript中求和的方法

javascript输出语句有哪些

彻底弄懂javascript执行机制

如何理解javascript中的原型链

javascript canvas方法有哪些

javascript match什么意思

javascript对象怎么转换成字符串

js (javascript)加密算法库 crypto-js 简介

javascript中怎么将字符串转为数字

javascript字符串方法有哪些

更多相关阅读请进入《javascript》频道 >>




打赏

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码打赏,您说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

分享从这里开始,精彩与您同在

评论

管理员已关闭评论功能...