Vue 2.x 响应式原理与双向绑定

Vue实例

Vue会把data中的数据成员注入到Vue的实例中去,并转成getter/setter访问器属性。
这样的目的是:
1.我们能够通过 this.xxx(this.属性名)的方式进行调用。
2.通过getter/setter进行数据劫持,实现数据监听。

data中的成员都被存放到了$data中,并且全部转换成访问器属性,即getter/setter,$data中的setter是真正监视数据变化的地方。

Vue的实例中还有一个_data,它与$data指向的是同一个对象(地址相同),只不过_data表示私有成员,而$data是公有成员。

Vue实例中的$options用来存放创建Vue实例时传递进来的参数(选项)。

Vue响应式原理

这里说一说最小模式的响应式原理。

  • Vue类,负责接收初始化的参数(选项)。
  • 然后会把data中的数据成员注入Vue的实例,并转成getter/setter。
  • Vue类的内部会调用Observer、Compiler
    • Observer对数据进行劫持,能够对data中的属性进行监听,如果数据发生变化,会获取到最新的值,并通知Dep。
    • Compiler会对每个元素进行解析,即解析每个元素中的指令(v-xxx)以及差值表达式({{ xxx}}),并替换成响应的数据。
    • Watcher就是观察者模式中的观察者又叫订阅者。它的内部有一个update方法,负责更新视图。
    • Dep就是观察者模式中的目标又叫发布者。负责添加观察者,当数据发生变化,通知所有的观察者调用update方法更新视图。
      在这里插入图片描述

_proxyData

在Vue类的内部,有个一个_proxyData的私有方法,负责把data中的数据成员,转成getter/setter并注入到Vue的实例中去,实现数据监听也方便后续使用(可以通过this.属性名的方式调用data中的数据)。

戳 → _proxyData

Observer

Observer类中有两个核心方法walk、definReactive。
walk 遍历data中的属性,并调用definReactive把数据转为getter/setter – 响应式。

当访问data中的数据时,即通过this.属性名获取/使用数据时,首先访问Vue实例(后统一叫做vm)中的get,因为Vue首先将data中的数据都转成了getter/setter并注入vm中。vm的get中通过data[属性名]来返回数据,而在Observer中将data中的数据转成了getter/setter存放到vm的$data中,所以会调用$data中的get。

即,
vm.属性名 → vm中的get → $data中的get
vm.属性名 = xxx → vm中的set → $data中的set → Observer中,在set发送数据变化通知

戳 → Observer

Compiler

Compiler类的作用用一句话总结就是在操作DOM。

核心功能:

  • 编译模板,处理差值表达式、指令。递归遍历vm.el中的所有子节点,判断:
    • 如果是文本节点,则处理差值表达式。
    • 如果是元素节点,则处理指令。

戳 → Compiler

Dep

Dep主要负责监听数据变化。Dep会在Observer的$data的get方法中收集依赖在set方法中触发依赖(发送通知)

Vue会为每一个响应式数据($data中的每个属性)创建一个Dep对象,在使用数据时收集依赖(即创建观察者对象 Watcher),在更新数据时通知所有(依赖数据的)观察者更新视图。

戳 → Dep

Watcher

Watcher主要负责更新视图,其次在自身实例化的时候会把自身实例添加到Dep类的target静态属性中。

Watcher中可以拿到oldVaule、newValue,以及callback。更新过程中去比较新、旧的值是否发生变化,如果发生变化,则调用callback并将newValue作为参数传递过去。这里的callback(回调)才是真正执行更新视图的方法。

所以,需要在所有依赖数据的地方创建Watcher对象,并传递一个更新视图数据的回调函数。当数据发生改变的时候,Dep会调用notify方法通知所有Watcher对象更新视图,其实就是通知Watcher执行回调。

戳 → Watcher

双向绑定

前面一系列操作~~都是数据驱动视图更新,那么,对于表单元素,当视图发生变化也应该更新数据。

input输入框举例。

当输入框中的值被修改,此时可以拿到被修改后的值,也就是inputvalue。然后再将value重新赋值给vm中的数据,即vm.xxx = input.value

戳 → 双向绑定

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值