亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

簡單實現(xiàn)vue中的依賴收集與響應的方法

 更新時間:2019年02月18日 15:17:43   作者:AwesomeHan  
這篇文章主要介紹了簡單實現(xiàn)vue中的依賴收集與響應的方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧

開始

聲明一個對象man,可以視為vue中的data

let man = {
 height: 180,
 weight: 70,
 wealth: 100000000
}

添加Observer

作用在于將參數(shù)對象的屬性變?yōu)轫憫?,只要對象的屬性被讀取或者被修改都能觀察到。然后新建一個Observer實例,將man作為參數(shù)扔進去。這里的proxyData是將man的屬性代理到以man為參數(shù)的Observer實例上去。

class Observer {
 constructor(obj) {
  this.walk(obj)
 }
 walk(obj) {
  Object.keys(obj).forEach(prop => {
   this[prop] = obj[prop]
   this.proxyData(obj, prop)
   this.defineReactive(this, prop, obj[prop])   
  })
 }
 proxyData(obj, prop) {
  let _this = this
  Object.defineProperty(obj, prop, {
   get() {
    return _this[prop]
   },
   set(newVal) {
    _this[prop] = newVal
   }
  })
 }
 defineReactive(obj, prop, val) {
  Object.defineProperty(obj, prop, {
   get() {
    console.log(`${prop} - 被讀??!`)
    return val
   },
   set(newVal) {
    if (newVal == val) return
    val = newVal
    console.log(`${prop} - 被修改!`)
   }
  })
 }
}

new Observer(man)

這時打印一下man


現(xiàn)在man的屬性都是由Observer實例所對應的屬性的getter來返回,只有在查看時會被觸發(fā)


對man的屬性進行修改也會觸發(fā)實例對應屬性的setter

添加Watcher

現(xiàn)在的Watcher有點像vue中的computed,實際上就是定義一個計算屬性,這個計算屬性依賴于前面man中的某些屬性,由他們計算而得。

class Watcher {
 constructor(obj, prop, computed) {
  this.getVal(obj, prop, computed)
 }

 getVal(obj, prop, computed) {
  Object.defineProperty(obj, prop, {
   get() {
    console.log(`computed屬性 - ${prop}被讀?。)
    return computed()
   },
   set() {
    console.error('計算屬性不可被修改!')
   }
  })
 }
}

new Watcher(man, 'strength', () => {
 let {height, weight} = man
 if (height > 160 && weight > 70) return 'strong'
 return 'weak'
})


看起來沒什么問題,所依賴的屬性如果變了,計算屬性只要再被查看(get方法)一次就可以更新了。但vue中的視圖渲染是實時的,視圖層依賴于數(shù)據(jù)層,數(shù)據(jù)變化了,視圖層也會跟著變化,不需要手動更新。類比到這個例子就是計算屬性如何才能在其所依賴的屬性發(fā)生變化時被通知從而觸發(fā)應有的事件?

這時我們先給Watcher加多一個callback,用于處理當依賴的數(shù)據(jù)被修改時,我這個計算屬性該怎么響應

比如當依賴被修改時,我們就把這個計算屬性的值打印出來

class Watcher {
 constructor(obj, prop, computed, callback) {
  this.getVal(obj, prop, computed, callback)
 }

new Watcher(man, 'strength', () => {
 let {height, weight} = man
 if (height > 160 && weight > 70) return 'strong'
 return 'weak'
}, () => {
 console.log(`i am so ${man.strength} !`)
})

一切都準備好了,接下來就是該如何實現(xiàn)?

我們先看下Watcher中getVal這個方法

getVal(obj, prop, computed, callback) {
 Object.defineProperty(obj, prop, {
  get() {
   console.log(`computed屬性 - ${prop}被讀??!`)
   return computed()
  },
  set() {
   console.error('計算屬性不可被修改!')
  }
 })
}

當我們查看計算屬性時,會調(diào)用computed這個方法,相當于查看了其所依賴的height和weight屬性,而在上面我們已經(jīng)讓man的所有屬性都擁有了get方法,即他們被查看時我們是不是可以把callback塞給他們?
這時候我們引進一個橋梁,來連接Watcher和Observer。

添加Dep

Dep的用處在于當某一個屬性(以下稱‘自己')被依賴了,將依賴自己的粉絲(們)--也就是Watcher(s),收集起來,假如自己發(fā)生了變化,能夠及時通知粉絲們。

class Dep {
 constructor() {
  this.deps = []
 }
 getDeps() {
  if (!Dep.target || this.deps.includes(Dep.target)) return
  console.log('依賴添加', Dep.target)
  this.deps.push(Dep.target)
 }
 notify() {
  this.deps.forEach(dep => {
   dep()
  })
 }
}

這里的Dep.target就是前面所說的callback方法了。這時我們改一下Watcher中的getVal

getVal(obj, prop, computed, callback) {
 Object.defineProperty(obj, prop, {
  get() {
   Dep.target = callback
   console.log(`computed屬性 - ${prop}被讀??!`)
   return computed()
  },
  set() {
   console.error('計算屬性不可被修改!')
  }
 })
}

在計算屬性被查看時,將callback賦值給Dep.target,接下來就會調(diào)用其所依賴屬性的getter,我們只要在getter里把callback給收集起來就行了。接下來修改依賴屬性的getter方法。

defineReactive(obj, prop, val) {
 let dep = new Dep()
 Object.defineProperty(obj, prop, {
  get() {
   console.log(`${prop} - 被讀??!`)
   dep.getDeps() // 依賴收集
   return val
  },
  set(newVal) {
   if (newVal == val) return
   val = newVal
   console.log(`${prop} - 被修改!`)    
  }
 })
}

這時watcher的callback都被依賴屬性給收集起來了,當依賴屬性發(fā)生變化時只要去運行這些callback就可以了。接下來就是修改依賴屬性的setter方法。

defineReactive(obj, prop, val) {
 let dep = new Dep()
 Object.defineProperty(obj, prop, {
  get() {
   console.log(`${prop} - 被讀??!`)
   dep.getDeps()
   return val
  },
  set(newVal) {
   if (newVal == val) return
   val = newVal
   console.log(`${prop} - 被修改!`)
   dep.notify() // 運行所有callback
  }
 })
}

運行看看


我們加多一個Watcher試試

new Watcher(man, 'isGreat', () => {
 let {height, weight, wealth} = man
 if (height > 180 && weight > 70 && wealth > 100000) return 'Great!'
 return 'not good enough ...'
}, () => {
 console.log(`they say i am ${man.isGreat}`)
})


這就是vue中的一個依賴對應多個Watcher

以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。

相關文章

最新評論