前端知识|Vue双向数据绑定原理

1.双向数据绑定—前置技术点 1.1 数组的reduce()方法
应用场景:下次操作的初始值,依赖于上次操作的返回值
【前端知识|Vue双向数据绑定原理】数组reduce方法,会循环当前的数组,侧重于进行“滚雪球”操作。
数组.reduce(函数,初始值)
const 累加结果 = 数组.reduce((上次计算结果,当前循环的Item项)=> {return 上次的结果 + 当前循环的Item项},0)

  • 1. 数值的累加计算
const total = arr.reduce((val,item)=>{return val+item},0)

  • 2. 链式获取对象属性的值
const obj = { name:'zy' info:{ address:{ location:'changsha' } } } const attrs = ['info', 'address', 'location'] //第一次reduce,初始值是obj这个对象,当前Item项是info,结果是obj.info属性对应的对象 //第二次reduce,初始值是obj.info这个对象,当前Item项是address,结果是obj.info.address属性对应的对象 //第三次reduce,初始值是obj.info.address这个对象,当前Item项是location,结果是obj.info.address.location属性的值 //const location = attrs.reduce((newObj, key)=>{return newObj[key]}, obj) const location = attrs.reduce((newObj, key)=> newObj[key], obj) console.log(location) //changsha//reduce链式获取对象属性值的升级操作,开发实际会用到 const attrStr = 'info.address.location' attrStr.split(',').reduce((newObj, key)=> newObj[key], obj)

1.2 发布订阅模式
  1. Dep类:负责进行依赖收集,
    首先,有个数组专门存放所有的订阅信息
    其次,还要提供一个向数组中追加订阅信息的方法
    然后,还要提供一个循环,循环触发数组中的每个订阅信息
  2. Watcher类:负责订阅一些事件
比如说有个百货商店,有A B C三个顾客,A想买雪碧,B想买可乐,C想买芬达,但是恰好都卖完了,老板就说那你们在这个本子上留下电话号码,等到货了我打电话通知你们。ABC顾客离开了,将来到货老板拿着本子分别打电话,通知顾客来取东西,这就是发布订阅模式。
这个收集信息的本子相当于Dep类,到一定的时机,就会循环每一个订阅信息,通知到位。 顾客ABC相当于Watcher类,把自己的一些行为交给了Dep类,存放将来要做的事情,将来Dep发现时机到了,开始广播通知,把收集到的依赖都进行触发,那么Watcher类就收到了对应的消息。
Dep类负责收集+触发,所以它的身上有两个方法,一个是向数组里添加订阅,一个是循环数组里每一项来发布订阅。
只要我们为Vue中data数据重新赋值了,这个赋值的动作,会被vue监听到,然后vue要把数据的变化,通知到每个订阅者! 接下来,订阅者(每个DOM元素)要根据最新的数据,更新自己的内容。
1.3 使用Object.defineProperty()进行数据劫持
  • 通过get()劫持取值操作
  • 通过set()劫持赋值操作
2.Vue响应式原理 当一个vue实例创建时,vue会遍历data中对象所有的属性,使用Object.defineProperty(Vue3使用的是proxy)把这些属性全部转成getter / setter。 而每个组件实例都有Watcher对象,会在组件渲染的过程中把属性记录成依赖, 之后当依赖项的setter被调用时,会通知Watcher重新计算,从而使得关联的组件得以更新。
前端知识|Vue双向数据绑定原理
文章图片

3. 双向数据绑定原理
  • Observer对象:vue中数据对象在初始化过程中转换成Observer对象
  • Watcher对象:将模板和Observer对象结合在一起生成Watcher实例,Watcher是订阅者中的订阅者
  • Dep对象:Watcher对象和Observer对象之间的纽带,每一个Observer都有一个Dep实例,用来存储订阅者Watcher
  • 当属性变化会执行Observer的dep.notify方法,这个方法会遍历订阅者Watcher列表向其发送消息,Watcher会执行run方法去更新视图。模板编译过程中的指令和数据绑定都会生成Watcher实例,实例中的Watcher属性也会生成Watcher实例。

    推荐阅读