Vue响应式原理
1、Vue内部如何监听message数据改变? Object.defineProperty
Object.defineProperty(obj, prop, descriptor)
obj:需要定义属性的对象
prop:要定义或修改的属性的名称或Symbol
descriptor:要定义或修改的属性描述符
2、数据改变,Vue如何通知刷新? 发布订阅模式
简单的发布订阅模式梳理(即图的上半部分,下半部分编译暂时不写):
1、首先定义一个数据data对象
const obj = { message: '111', age: 18 }
2、使用object.defineProperty来劫持数据。forEach遍历obj内的属性,通过set和get函数进行指定操作:set监听改变情况并赋新值;get拿到当前值
Object.keys(obj).forEach(key => { let value = obj[key] //劫持 Object.defineProperty(obj, key, { //设置,改变值,赋新值newValue set(newValue) { //监听某个值的改变,这里是message,当然,要是obj内还有多个数据,就遍历整个obj,对指定的key进行改变 console.log('监听到改变 ' + key); value = newValue //解析HTMl代码获取哪些元素需要该属性,这时就来到get //需要用的元素会调用get,一旦set后,便通知所需要改变的元素:发布订阅模式 dep.notify() }, //获取值,拿到原Value get() { //获取改变值 console.log('已经拿到已有值'); return value } }) })
这一步即可在控制台改变数据,log打印监听到何值改变或者拿到何值
3、分别定义订阅者和发布者:
3.1:订阅者:保存元素的名称,并使用update函数更新
class Watcher { constructor(name) { //保存某个元素 this.name = name } update() { console.log(this.name + '元素发生update'); } }
3.2:发布者:首先构造函数将所要监听的订阅者放置一个数组内(即元素,这里要注意,每一个元素每一个属性都对应一个dep,这样才能针对不同的元素,不同的属性发布不同的内容),然后执行notify通知函数(其实就是forEach遍历数组内的watcher,执行内部的update函数)
//发布:一个属性对应一个Dep,message一个,age一个,这样才能针对不同的对象,不同的属性进行分别通知或者说发布 class Dependence { constructor() { //记录那些元素需要订阅数据 this.subscribes = [] } addSub(watcher) { this.subscribes.push(watcher) } notify() { console.log('发布') this.subscribes.forEach(item => { item.update() }) } }
4、执行过程:new一个dep监听数据改变,在new多个需要监听的watcher,将watcher推入dep中准备发布
const dep = new Dependence() //某个元素已经被创建保存,element1 const watch1 = new Watcher('el1') //元素加入到dep内记录监听 dep.addSub(watch1)
执行结果:
其他的就是下半部分的compile,上述为手动push