手撸vue双向绑定

209 阅读1分钟

正常运行的demo1

let price = 10
let quantity = 2
let total = 0
let target = () => {  
    total = price * quantity}target()
}

只会一次求值

如果想要多次求值只能加存起来,因此有了storage

加入storage  demo2

let price = 10
let quantity = 2
let total = 0
let storage = []
let target = () => {  
    total = price * quantity
}
let record = () => {  
    storage.push(target)
}
let replay = () => {  
    storage.forEach(run => run())
}
record() //先记录一次
target() // 求值 20

// 改变 
let price = 20
replay() // total 40

这里还是需要手动调用,按照目标,应该是自动调用,自动调用就应该依附于具体的单个属性

加入Dep demo3

class Dep {  
   add () {
     //不需要多次添加    
   if (target && !storage.includes(target)) {
      storage.push(target)    
     }  
   }  
   notify () {    
     storage.forEach(run => run())  
   }
}
let dep = new Dep()
let price = 10
let quantity = 2
let total = 0
let storage = []
let target = () => {  
     total = price * quantity
 }
dep.add()
dep.notify()

这次依然需要手动调用,只不过比较语义化了,接下来和每个属性绑定

响应式对象 demo4

  class Dep {  
    constructor () {    
      this.storage = []  
     }  
     depend () {    
       if (target && !this.storage.includes(target)) {      
          this.storage.push(target)     
         }  
      }  
     notify () {    
        this.storage.forEach(run => run())  
      }
    }
  let data = {  
     price: 20,  
     quantity: 2
   }
let total  = 0, salePrice = 0, target
function Watcher (func) {  
    target = func  
    target()  
    target = null
}
 //这里遍历我们需要绑定的data对象  
Object.keys(data).forEach(key => {    
  let intervalValue = data[key]    
  let dep = new Dep()    
  Object.defineProperty(data, key, {      
       get () {        
          dep.depend()        
          return intervalValue      
       },      
       set (val) {        
          intervalValue = val        
          dep.notify()      
       }   
     })  
})  
new Watcher(() => {    
   total = data.price * data.quantity  
  })  
new Watcher(() => {    
   salePrice = data.price * 0.5  
  })

这里的watcher更像是对代码做了一层封装,watcher的target是一个函数,每个属性都是一个新的dep,一个watcher对象可能同时属于好几个dep对象,这里price的storage有两个watcher,

quantity只有一个watcher 

最后放一个vue的双向绑定部分源码