Vue的响应式原理是通过数据劫持+观察者模式来实现的
数据劫持
观察vue中打印出来的数据发现有奇奇怪怪的get,set,这是因为Vue会对data中数据进行数据劫持,并对data中的数据进行数据代理
-
Vue中的数据代理
- 通过vm对象来代理data对象中的属性的操作(读/写)
-
Vue中数据代理的好处
- 更加方便的操作data中的数据
-
基本原理
- 通过Object.defineProperty()把data对象中所有的属性添加到vm上。为每一个添加vm上的属性,都指定一个getter/setter.在getter/setter内部去操作(读/写)data中对应的属性
-
模拟Vue的数据代理 `
let data = { name: '尚硅谷', address: '北京' } // 创建一个实例对象,用于监视data中属性的变化 const obs = new Objserver(data) console.log(obs); // 准备一个vm实例对象 let vm = {}; vm._data = data = obs; function Objserver(obj) { // 汇总对象中所有的属性形成一个数组 const keys = Object.keys(obj); //遍历 keys.forEach(function(k){ Object.defineProperty(this,k,{ get(){ return obj[k]; }, set(val){ console.log(`${k}被改了,我要去解析模板,生成虚拟DOM......我要开始忙了`); obj[k] = val; } }) }) }`
-
实现一个迷你版的数据响应式
观察者模式
- 定义: 定义对象间一种“一对多”的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知
- 与发布订阅模式的区别:少了一个中间代理,发布者直接面向订阅者
- 观察者模式的的四大核心类
- Observer类: (数据劫持)数据的观察者,让数据对象的读写操作都处于自己的监管之下
- Watcher类:数据的订阅者,数据的变化会通知到Watcher,然后由Watcher进行相应的操作,例如更新视图
- Dep类:上带有添加、解绑以及通知订阅者的方法;Observer把数据进行劫持从而数据变了我们是知道的,但是数据变了谁去通知订阅者呢?是Dep 它是 Observer与Watcher的纽带,当数据变化时,会被Observer观察到,然后由Dep通知到Watcher
- Compile类: Compile干的活是解析模板指令,将模板中的变量替换成数据,然后初始化渲染视图,并将每个指令对应的节点绑定更新函数,监听数据的订阅者,一旦有异动,就去更新视图
总结:
- 数据劫持的目的是:数据变了的时候程序知道
- 观察者模式:一个数据变了 视图中多个地方都会变
话术:
- vue是响应式,所谓的响应式是指数据发生改变的时候,视图会重新渲染,vue实现响应式的原理是数据劫持和观察者模式 数据劫持实现了数据改变程序是知道的,观察者模式实现了当一个数据变了,视图中多个用到的地方跟着变
- 实现原理是:
- 首先,通过Observer类对data中的数据利用Object.defineProperty进行数据劫持把data中所有的属性转换成getter和setter的写法,在getter中会让每个数据都创建一个发布者dep实例对象,一个数据对应一个dep实例
- 然后,通过Compile类对模板进行编译得到和data中属性相对应的Watcher订阅者,把订阅者加入到dep中,这是一对多的关系
- 最后,当data中数据改变的时候,会通知对应的dep,dep会对这个数据相对应的所有的订阅者Watcher进行遍历通知, Watcher会更新相对应的视图