首页 >> 大全

剖析Vue数据劫持的实现原理

2023-09-12 大全 28 作者:考证青年

原文:(包含原文源码)

由于源码的注释比较少,我自己加了注释的地址:

双向数据绑定方法 发布者-订阅者模式 - 微信小程序, React脏值匹配 – 数据劫持 – vue 发布者-订阅者模式

一般通过方法实现数据和视图的绑定监听,更新数据通常做法为vm.set(‘’, value)

脏值匹配

.js 是通过脏值检测的方式比对数据是否有变更,来决定是否更新视图,最简单的方式就是通过 () 定时轮询检测数据变动,当然不会这么low,(用一些监听)只有在指定的事件触发时进入脏值检测,大致如下

数据劫持

vue中数据劫持解析图

:数据监听器,能够对data中全部属性进行监听,如果数据有变动可以拿到最新值,并且通知订阅者()

通过 . 设置为存储描述符

: 指令解析器,对元素上的指令和{{}}中的文本进行扫描和解析,根据指令模板替换数据,以及绑定相应的更新函数

:订阅器,作为连接和的桥梁

大概流程 执行函数(数据监听器)对data中的全部属性进行监听,并且对其用.中的存储描述符来添加get()和set()方法,并且构建了相关的dep对象,使其如果data中的数据发生修改那么就会通知Dep(但是在开始阶段Dep还是没有创建的,在后续创建)执行(指令解析器):来初始化页面对node中的文本节点和元素节点进行解析,通过方法来对node进行渲染,在初始化的过程中我们对那些文本节点和元素(指令)节点进行new 构造函数进行,构造相关对象(包括了当前表达式exp对应的值,和vm对象,和回调函数),这里的回调函数是Vue对指令或{{}}的语法糖的函数执行,同时对当前文本节点或者指令节点的表达式进行了执行一遍

  /*** {{}} 文本实例  -->这个只是大概的展示 并不是源码内容* @param {*} node // 当前文本节点* @param {*} value // 需要赋值的值*/textUpdater: function (node, value) {node.textContent = typeof value == 'undefined' ? '' : value; // 对节点的textContent赋值},

而在构架的时候我们会对表达式中的值读取一遍,为什么呢?(例如下面的例子{{a.b.c}}) 其实就是为了触发我们前面在中对每一个data设置的访问器属性get,作用就是把当前,通过执行原型链上的方法将其放入到相关联的Dap的subs数组中(也就是说subs数组中放的是),那么触发set访问器函数的时候就会找到相关Dep中的subs数组那么我们每一个data就有一个Dep,而这个Dep中又包含了subs数组,subs数组中包含了,当某一个值发生改变遍历subs,找到和data相关的,而这个在触发他相关的回调函数,并且由于中包含了vm对象因此可以通过就会去找到相关的node去和改变表达式的值 简单概述Dep

data每一个值都有一个Dep,Dep中有subs数组,其包含了,所以当某一个data数据发生了改变就会遍历Dep中的subs数组中的,通过中包含了(包括了当前表达式exp对应的值,和vm对象,和回调函数),所以可以通过vm对象找到相关Dom去触发回调函数来改变相关值

注意

例如一个表达式{{A.B.C}}我们表达式只是获取c的值但是这个c这个值相关的分别会放入到a,a.b,a.b.c的Dpe中的subs数组中,主要当a修改那么a.b,a.b.c相关的就会被触发,那么相关的回调函数触发修改node,那么vue是如何做到的呢,其实就是我们遍历如果要获取a.b.c要首先获取到a的值,在获取到a.b的值,那么在获取对应值的时候触发了get()函数,就会把当前表达式{{a.b.c}}所关联的放入到对应的Dep的subs数组中

 getVMVal: function () {var exp = this.exp.split('.');var val = this.vm._data; // 初始为data 如果exp为a.b.c 那么过程为 data.a  data.a.b  data.a.b.cexp.forEach(function (k) {val = val[k];});return val;}

关于我们

最火推荐

小编推荐

联系我们


版权声明:本站内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 88@qq.com 举报,一经查实,本站将立刻删除。备案号:桂ICP备2021009421号
Powered By Z-BlogPHP.
复制成功
微信号:
我知道了