Vue源码分析

Vue源码分析

数据代理

1. 数据代理

数据代理是通过一个对象代理对另一个对象中属性的操作(读/写)。

Vue中的数据代理是通过vm对象来代理data对象中所有属性的操作。优点是能够更方便的操作data中的数据

2. 基本实现流程

  1. 通过Object.defineProperty()vm添加与data对象的属性对应的属性描述符。
  2. 所有添加的属性都包含getter/setter
  3. getter/setter内部去操作data中对应的属性数据。

模板解析

1. 模板解析的基本流程

  1. 将el的所有子节点取出, 添加到一个新建的文档fragment对象中

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

    • 对大括号表达式文本节点进行解析

    • 对元素节点的指令属性进行解析

      • 事件指令解析

      • 一般指令解析

  3. 将解析后的fragment 添加到el 中显示

2. 大括号表达式解析

  1. 根据正则对象得到匹配出的表达式字符串: 子匹配/RegExp.$1
  2. 从data 中取出表达式对应的属性值
  3. 将属性值设置为文本节点的textContent

3. 事件指令解析

  1. 从指令名中取出事件名
  2. 根据指令的值(表达式)从methods中得到对应的事件处理函数对象
  3. 给当前元素节点绑定指定事件名和回调函数的dom事件监听
  4. 指令解析完后,移除此指令属性

4. 一般指令解析

  1. 得到指令名和指令值(表达式)
  2. data中根据表达式得到对应的值
  3. 根据指令名确定需要操作元素节点的什么属性
    • v-text—textContent 属性
    • v-html—innerHTML 属性
    • v-class–className 属性
  4. 将得到的表达式的值设置到对应的属性上
  5. 移除元素的指令属性

数据绑定

1. 数据绑定

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

2. 数据劫持

  1. 数据劫持是Vue中用来实现数据绑定的一种技术
  2. 基本思想:通过Object.defineProperty()来监视data中所有属性(任意层次)数据的变化,一旦变化就去更新页面。

3. 四个重要对象

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

  2. 给data中所有属性重新定义属性描述(主要是get/set方法)

  3. 为data中的每个属性创建对应的Dep对象

2. Dep (Depend)
  1. data中的每个属性(所有层次)都对应一个Dep对象

  2. 它的实例在什么时候创建?

    初始化中的给data的属性进行数据劫持时创建的。

    • 在初始化在初始化 define data 中各个属性时创建对应的 dep 对象
    • 在 data 中的某个属性值被设置为新的对象时
  3. 它的数量是多少?

    data中的属性是一一对应的。

  4. Dep对象的结构

{
    id: 0, // 每个dep都有一个唯一标识id,
    subs: [] // n个相关的Watcher对象的容器(数组)
}
  1. subs属性说明
    • 当Watcher被创建时,内部将当前watcher 对象添加到对应的 dep 对象的subs 中
    • 当此 data 属性的值发生改变时, subs 中所有的 watcher 都会收到更新的通知,从而最终更新对应的界面
3. Compiler
  1. 用来解析模板页面的对象的构造函数(一个实例)
  2. 利用 compile 对象解析模板页面
  3. 每解析一个表达式(非事件指令)都会创建一个对应的 watcher 对象, 并建立 watcher 与 dep 的关系
  4. complier 与 watcher 关系: 一对多的关系
4. Watcher
  1. 模板中每个非事件指令或表达式都对应一个 watcher 对象

  2. 监视当前表达式数据的变化

  3. 它的实例在什么时候创建?

    初始化中的解析大括号表达式/一般指令时创建。

  4. 它的数量是多少?

    与模板中表达式(不包含事件指令)的个数一一对应。

  5. Watcher对象的数据结构

this.cb = cb  // 当表达式所对应的数据发生改变时用于更新界面的回调函数
this.vm = vm  // vm对象
this.exp = exp  // 对应指令的表达式
this.depIds = {"depid": "dep"}  // 相关的n个Dep对象的容器(对象)
this.value = this.get()  // 当前表达式对应的value值
5. Dep与Watcher之间的关系
  • 什么关系?

    多对多的关系。

    • data属性 -> Dep -> n个Watcher(n>1:当模板中有多个表达式使用了此属性时:{{ a }} v-text="a"
    • 表达式 -> Watcher -> n个Dep(n>1:当使用多层表达式时:a.name.last
  • 如何建立关系?

    使用data中属性的get方法中建立。

  • 什么时候建立的?

    初始化的解析模块中的表达式创建Watcher对象时建立。

  • 数据绑定使用到 2 个核心技术

    • Object.defineProperty()
    • 消息订阅与发布

MVVM原理图分析

在这里插入图片描述

初始化

Compile -> Watcher: 为表达式创建对应的watcher,指定更新的函数

Dep: 与data中的属性一一对应

  • subs: 保存n个Watcher的数组容器
更新

Dep -> Watcher: 通知所有相关的Watcher

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QhbxZkDF-1626253008691)(F:\技术资料\前端面试知识点\MVVM.png)]

双向数据绑定

  1. 双向数据绑定是建立在单向数据绑定(model==>View)的基础之上的
  2. 双向数据绑定的实现流程:
    1. 在解析 v-model 指令时, 给当前元素添加事件监听(输入框触发方式为input)
    2. 当 input 的 value 发生改变时, 将最新的值赋值给当前表达式所对应的 data 属性

MVVM原理图分析

[外链图片转存中…(img-EkVatygv-1626253008689)]

初始化

Compile -> Watcher: 为表达式创建对应的watcher,指定更新的函数

Dep: 与data中的属性一一对应

  • subs: 保存n个Watcher的数组容器
更新

Dep -> Watcher: 通知所有相关的Watcher

在这里插入图片描述

双向数据绑定

  1. 双向数据绑定是建立在单向数据绑定(model==>View)的基础之上的
  2. 双向数据绑定的实现流程:
    1. 在解析 v-model 指令时, 给当前元素添加事件监听(输入框触发方式为input)
    2. 当 input 的 value 发生改变时, 将最新的值赋值给当前表达式所对应的 data 属性
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值