vue源码分析之实现observer和watcher(一)

Vue干货 小白 暂无评论

实现$wacth



const v = new Vue({
 data:{
   a:1,
   b:2
 }
})
v.$watch("a",()=>console.log("哈哈,$watch成功"))
setTimeout(()=>{
 v.a = 5
},2000) //打印 哈哈,$watch成功

1.实现observer



export default class  Observer{
 constructor(value) {
   this.value = value
   this.walk(value)
 }
 //递归。。让每个字属性可以observe
 walk(value){
   Object.keys(value).forEach(key=>this.convert(key,value[key]))
 }
 convert(key, val){
   defineReactive(this.value, key, val)
 }
}

export function defineReactive (obj, key, val) {
 var childOb = observe(val)
 Object.defineProperty(obj, key, {
   enumerable: true,
   configurable: true,
   get: ()=>val,
   set:newVal=> {      
    childOb = observe(newVal)//如果新赋值的值是个复杂类型。再递归它,加上set/get。。
    }
 })
}

export function observe (value, vm) {
 if (!value || typeof value !== 'object') {
   return
 }
 return new Observer(value)
}

代码很简单,就给每个属性(包括子属性)都加上get/set,

这样的话,这个对象的,有任何赋值,就会触发set方法。。

所以,我们是不是应该写一个消息-订阅器呢?这样的话,

一触发set方法,我们就发一个通知出来,然后,订阅这个消息的,就会怎样?。。。对咯。。收到消息。。。触发回调。

2.消息-订阅器



export default class Dep {
 constructor() {
   this.subs = []
 }
 addSub(sub){
   this.subs.push(sub)
 }
 notify(){
   this.subs.forEach(sub=>sub.update())
 }
}

所以,每次set函数,调用的时候,我们是不是应该,触发notify,对吧。所以
我们把代码补充完整

    
   
   export function defineReactive (obj, key, val) {
     var dep = new Dep()
     var childOb = observe(val)
     Object.defineProperty(obj, key, {
       enumerable: true,
       configurable: true,
       get: ()=>val,
       set:newVal=> {
         var value =  val
         if (newVal === value) {
           return
         }
         val = newVal
         childOb = observe(newVal)
         dep.notify()
       }
     })
   }

那么问题来了?谁是订阅者,对,是Watcher。。一旦 dep.notify()

就遍历订阅者,也就是Watcher,并调用他的update()方法


转载请注明: Vue教程中文网 - 打造国内领先的vue学习网站-vue视频,vue教程,vue学习,vue培训 » vue源码分析之实现observer和watcher(一)

喜欢 ()or分享