Vue----源码学习-基本实现原理(数据代理、模板编译、数据绑定的实现、双向数据绑定)

最近在学习Vue的源码,之前刚开始接触Vue的时候也是我刚开始学习开发,我看完了Vue官方文档就去网上找Vue源码的资料来看,看的是一脸懵逼。现在对Vue有一点了解之后再去看总于能看懂了。

Vue作为一个MVVM框架的基本实现原理包含数据代理模板编译数据绑定、双向数据绑定

数据代理:

解释:用过一个对象代理对另一个对象(在前一个对象内部)中属性的操作(读/写)

Vue数据代理:通过vm对象来代理data中所有属性的操作

好处:更方便的操作data中的数据

基本实现流程:

  1.通过Object.defineProperty()给vm添加与data对象属性对应的属性描述符

  2.所有添加的属性都添加了getter/setter函数

  3.通过getter/setter内部去操作data中对应的属性数据

模板编译:

Vue模板编译:将Vue的大括号表达式和指令(一般指令、事件指令)初始化显示

基本流程:

  1.去除el的所有子节点,添加到一个新的fragment对象中

  2.对fragment中的所有层次子节点进行递归编译处理

    a.对大括号表达式文本进行编译

    b.对节点指令属性进行编译(包含一般指令与事件指令

  3.将编译完成之后的fragment添加到el中

编译大括号表达式

  1.根据正则表达式得到匹配出的表达式字符串:子匹配/RegExp.$1

  2.从data中取出表达式对应的属性值

  3.将属性值设置为文本节点的textcontent

编译事件指令

  1.从指令名中取出事件名

  2.根据指令的值(表达式)从methods中得到对应的事件处理函数对象

  3.给当前元素点绑定指令事件名和回调函数的dom事件监听

  4.指令编译完成后,移出此指令属性

编译一般指令

  1.得到指令名和指令值(表达式)指令名通常为通常为text/html/class

  2.从data中根据得到的表达式取出对应的值

  3.根据指令确定需要操作元素节点的什么属性

    a.v-text--->textContent

    b.v-html--->innerHTML

    c.v-class--->className

  4.将得到的表达式的值设置到对应的属性上

  5.移出元素的指令属性

数据绑定:

效果:一旦更新了data中的某个属性数据,所有界面上直接使用或间接使用了此属性的节点都会更新

实现:是有数据劫持技术实现的数据绑定

数据劫持:

  1.数据劫持是Vue中实现数据绑定的一种技术

  2.基本思想:通过defineProperty()来监视data中所有属性(所有层次)的变化,一旦改变就去更新界面

四个重要对象:

  1.Observer:

    a.用来对data所有属性数据进行劫持的构造函数

    b.给data中所有属性重新定义属性描述(get/set)

    c.给data中的每个属性创建对应的dep对象

  2.dep(depend)

    a.data中的每个属性(所有层次)都对应一个dep对象

    b.创建时机:

      * 在定义data中各个属性时创建对应的dep对象

      * 在data中的某个属性值被设置为新的对象时

    c.对象的结构:

      {id://每个dep都有一个唯一的ID

       subs://包含n个对应watcher的数组(subscribes的简写)}

    d.subs属性说明:

      * 当watcher被创建时,内部将当前watcher对象添加到对应的dep对象的subs中

      * 在此data竖向的值发生改变时,subs中所有的watcher都会受到更新的通知,从而更新页面

  3.compiler

    a.用来编译模板页面的对象的构造函数(一个实例)

    b.利用compile对象来编译模板页面

    c.没编译一个表达式(非事件指令)都会创建一个对应的watcher对象,并建立watcher与dep的关系

    d.complie与watcher的关系:一对多的关系

  4.watcher

    a.模板中每个非事件指令或表达式都对应一个watcher对象

    b.监视当前表达式数据的裱花

    c.创建时间:在初始化编译模板时

    d.对象的属性:

    {

      vm, //vm对象

      exp, //对应指令的表达式

      cb, //当表达式所对应的数据发生改变时的回调函数

      value, //表达式当前的值

      depIds, //表达式中各级属性所对应的drp对象的集合对象

          //属性名为dep的id,属性值为dep

      }

  5.总结:

    a.data中的一个属性对应一个dep,一个dep中可能包含多个watcher(模板中有多少个表达式用到了同一属性)

    b.模板中一个非事件表达式对应一个watcher,一个watcher中可能包含多个dep(表达式是多层a.b)

    c.数据绑定使用到两个核心技术

      * defineProperty()

      * 消息订阅与发布

MVVM结构图:

现在我们根据图再来看看整个Vue的基本实现原理

初始化视图:

创建一个vm对象->创建observer(劫持/监视data里面所有的属性),同时为每一个属性创建dep(与data中的属性一一对应)

创建一个vm对象->创建compile(编译模板中的指令与大括号表达式)->调用updater(初始化视图),同时为表达式创建对应的watcher并绑定更新的函数->添加订阅者(将watcher添加到对应的dep的subs属性中,也就是建立两者的关系)

更新视图:

更新vm对象的属性->通知cbserver的set方法->通知dep->通知所有相关的watcher->调用updataer去更新视图

双向数据绑定:

  1.双向数据绑定建立在单向数据绑定(model==>View)的基础上的

  2.双向数据绑定的实现流程:

    a.在解析v-model指令时,给当前元素添加input监听

    b.当input的value发生改变时,将最新的值赋值给当前表达式所对应的data属性

原文地址:https://www.cnblogs.com/si-dian/p/12850926.html