美文网首页
vue双向绑定原理的思考

vue双向绑定原理的思考

作者: victoriasuli | 来源:发表于2018-05-30 08:06 被阅读0次

    1.初始化时data的值如何渲染进DOM?

    2.元素节点改变了值,怎样通知data里的值改变?

    3.data里的值改变,怎么通知文本节点中的属性值改变?


    1.初始化时data的值如何渲染进DOM?

    遍历所有DOM节点,如果有绑定data中的值的节点,把值赋给节点

    需要一个仓库,createDocumentFragment(),里面放所有节点,把值替换完成后,再将这个仓库整体插入到DOM中,此番操作能减少操作DOM的开销。

    创建仓库

    compile函数,是判断节点的类型并赋值的一个函数。节点按类型分为元素节点和文本节点:

    如果是文本节点,直接用正则表达式取两个大括号里的值作为data的key,再将data[key]赋给这个属性。

    如果是元素节点,首先遍历节点上的所有属性,如果有属性是‘v-model’,则取v-model绑定的属性作为data的key值,再将data[key]赋给这个属性。

    判断节点并赋值 vue实例

    2.元素节点改变了值,怎样通知data里的值改变?

    对于元素节点,在之前的compile函数中,给带有v-model的节点加监听,一旦值发生改变,则将变化值赋给data中对应的值。

    3.data里的值改变,怎么通知文本节点中的属性值改变?

    需要在data变化之后做点儿什么,先对data里的所有属性来个劫持,利用defineProperty劫持他们的get,set方法

    vue实例化时 属性劫持

    我们应该在set的时候,将newVal通知给文本元素进行更新,但是问题是,哪一个节点应该对应哪一个属性?

    我们可以在每个data的属性上绑定一个容器(依赖),在一开始初始化时,拿data中的值时,会调用get方法。我们在get里,只要一调用,就把这个节点push进依赖,等到set的时候,遍历这个依赖里的节点,进行赋值。

    这个依赖应该具备两个方法,一个是添加,一个是通知。

    addsubs方法将所有节点记录下来,push进数组;notify通知文本节点完成值的替换。

    依赖原型链上的方法 属性劫持时干的活儿

    至于,啥时候开始push节点呢?得等建立连接之后,也就是判断有没有v-model,如果有就取data中的值,赋给节点的值,在这之后push。

    除了push节点,我们还需要更新的函数,我们在这里封装一个容器,其中包含了节点,以及自身的更新函数。这个容器就是订阅者,watcher。watcher:

    1.watcher构造方法里首先把Dep设为有值的,然后执行update方法。

    2.在update方法中,首先去取data中的值,这就触发了属性劫持的get方法,并且现在全局标志Dep不为空。这个时候,在属性劫持的get方法中,依赖dep就把订阅者watcher push进去了。

    然后取到值,给节点赋值(我觉得这里就是初始化的赋值)。

    3.之后完成初始化的赋值,把全局标志置为null,作用是:等下次调用更新方法时,还会触发属性劫持的get方法,到这时候不会再往dep里push了。

    总结:

    1.两类DOM节点,带{{}}的文本节点,和带v-model的元素节点,这两类节点以及自身的更新方法被封装成watcher,即订阅者。

    2.每个data中双向绑定的属性,每个属性上都有依赖Dep,依赖里带有通知和添加两个方法。即发布者。

    3.Object.defineProperty

    set:dep.notify

    get : dep.addSubs();

            this.subs.push(watcher)

    相关文章

      网友评论

          本文标题:vue双向绑定原理的思考

          本文链接:https://www.haomeiwen.com/subject/fdlpkftx.html