成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

簡(jiǎn)單實(shí)現(xiàn)vue中的依賴收集與響應(yīng)

SexySix / 513人閱讀

摘要:但中的視圖渲染是實(shí)時(shí)的,視圖層依賴于數(shù)據(jù)層,數(shù)據(jù)變化了,視圖層也會(huì)跟著變化,不需要手動(dòng)更新。被讀取被修改運(yùn)行所有運(yùn)行看看我們加多一個(gè)試試這就是中的一個(gè)依賴對(duì)應(yīng)多個(gè)

開(kāi)始

聲明一個(gè)對(duì)象man,可以視為vue中的data

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

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

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)

這時(shí)打印一下man


現(xiàn)在man的屬性都是由Observer實(shí)例所對(duì)應(yīng)的屬性的getter來(lái)返回,只有在查看時(shí)會(huì)被觸發(fā)


對(duì)man的屬性進(jìn)行修改也會(huì)觸發(fā)實(shí)例對(duì)應(yīng)屬性的setter

添加Watcher

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

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("計(jì)算屬性不可被修改!")
      }
    })
  }
}

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


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

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

比如當(dāng)依賴被修改時(shí),我們就把這個(gè)計(jì)算屬性的值打印出來(lái)

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} !`)
})

一切都準(zhǔn)備好了,接下來(lái)就是該如何實(shí)現(xiàn)?

我們先看下Watcher中g(shù)etVal這個(gè)方法

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

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

添加Dep

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

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就是前面所說(shuō)的callback方法了。這時(shí)我們改一下Watcher中的getVal

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

在計(jì)算屬性被查看時(shí),將callback賦值給Dep.target,接下來(lái)就會(huì)調(diào)用其所依賴屬性的getter,我們只要在getter里把callback給收集起來(lái)就行了。接下來(lái)修改依賴屬性的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} - 被修改!`)       
    }
  })
}

這時(shí)watcher的callback都被依賴屬性給收集起來(lái)了,當(dāng)依賴屬性發(fā)生變化時(shí)只要去運(yùn)行這些callback就可以了。接下來(lái)就是修改依賴屬性的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()  // 運(yùn)行所有callback
    }
  })
}

運(yùn)行看看


我們加多一個(gè)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中的一個(gè)依賴對(duì)應(yīng)多個(gè)Watcher

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/101580.html

相關(guān)文章

  • 深入淺出Vue響應(yīng)式原理

    摘要:總結(jié)最后我們依照下圖參考深入淺出,再來(lái)回顧下整個(gè)過(guò)程在后,會(huì)調(diào)用函數(shù)進(jìn)行初始化,也就是過(guò)程,在這個(gè)過(guò)程通過(guò)轉(zhuǎn)換成了的形式,來(lái)對(duì)數(shù)據(jù)追蹤變化,當(dāng)被設(shè)置的對(duì)象被讀取的時(shí)候會(huì)執(zhí)行函數(shù),而在當(dāng)被賦值的時(shí)候會(huì)執(zhí)行函數(shù)。 前言 Vue 最獨(dú)特的特性之一,是其非侵入性的響應(yīng)式系統(tǒng)。數(shù)據(jù)模型僅僅是普通的 JavaScript 對(duì)象。而當(dāng)你修改它們時(shí),視圖會(huì)進(jìn)行更新。這使得狀態(tài)管理非常簡(jiǎn)單直接,不過(guò)理解...

    yiliang 評(píng)論0 收藏0
  • 淺析Vue響應(yīng)式原理(一)

    摘要:淺析響應(yīng)式原理一的特點(diǎn)之一是響應(yīng)式,視圖隨著數(shù)據(jù)的更新而更新,在視圖中修改數(shù)據(jù)后實(shí)例中的數(shù)據(jù)也會(huì)同步更新。對(duì)于每個(gè)響應(yīng)式數(shù)據(jù),會(huì)有兩個(gè)實(shí)例,第一個(gè)是在中的閉包遍歷,用途顯而易見(jiàn)。接收一個(gè)回調(diào)函數(shù),會(huì)在重新求值且值更新后執(zhí)行。 淺析Vue響應(yīng)式原理(一) Vue的特點(diǎn)之一是響應(yīng)式,視圖隨著數(shù)據(jù)的更新而更新,在視圖中修改數(shù)據(jù)后Vue實(shí)例中的數(shù)據(jù)也會(huì)同步更新。內(nèi)部借助依賴(下文中的Dep類)...

    lookSomeone 評(píng)論0 收藏0
  • 響應(yīng)式數(shù)據(jù)數(shù)據(jù)依賴基本原理

    摘要:響應(yīng)式數(shù)據(jù)響應(yīng)式數(shù)據(jù)不是憑空出現(xiàn)的。對(duì)于對(duì)象而言,如果是之前不存在的屬性,首先可以將進(jìn)行響應(yīng)化處理比如調(diào)用,然后將對(duì)具體屬性定義監(jiān)聽(tīng)比如調(diào)用函數(shù),最后再去做賦值,可能具體的處理過(guò)程千差萬(wàn)別,但是內(nèi)部實(shí)現(xiàn)的原理應(yīng)該就是如此僅僅是猜測(cè)。 前言   首先歡迎大家關(guān)注我的Github博客,也算是對(duì)我的一點(diǎn)鼓勵(lì),畢竟寫東西沒(méi)法獲得變現(xiàn),能堅(jiān)持下去也是靠的是自己的熱情和大家的鼓勵(lì)。   國(guó)內(nèi)前端算...

    or0fun 評(píng)論0 收藏0
  • Vue原理】響應(yīng)式原理 - 白話版

    摘要:所以我今后打算把每一個(gè)內(nèi)容分成白話版和源碼版。有什么錯(cuò)誤的地方,感謝大家能夠指出響應(yīng)式系統(tǒng)我們都知道,只要在實(shí)例中聲明過(guò)的數(shù)據(jù),那么這個(gè)數(shù)據(jù)就是響應(yīng)式的。什么是響應(yīng)式,也即是說(shuō),數(shù)據(jù)發(fā)生改變的時(shí)候,視圖會(huì)重新渲染,匹配更新為最新的值。 寫文章不容易,點(diǎn)個(gè)贊唄兄弟專注 Vue 源碼分享,文章分為白話版和 源碼版,白話版助于理解工作原理,源碼版助于了解內(nèi)部詳情,讓我們一起學(xué)習(xí)吧研究基于 V...

    gggggggbong 評(píng)論0 收藏0
  • Vue簡(jiǎn)單實(shí)現(xiàn)原理

    摘要:需要指令解析器,對(duì)每個(gè)元素節(jié)點(diǎn)的指令進(jìn)行掃描和解析,根據(jù)指令模板替換數(shù)據(jù),以及綁定相應(yīng)的更新函數(shù)。然后將模版中的變量替換成數(shù)據(jù),渲染,將每個(gè)指令對(duì)應(yīng)的節(jié)點(diǎn)綁定更新函數(shù),添加監(jiān)聽(tīng)數(shù)據(jù)的訂閱者,一旦數(shù)據(jù)發(fā)生變動(dòng),收到通知,更新視圖。 用了Vue也有兩年時(shí)間了,一直以來(lái)都是只知其然,不知其所以然,為了能更好的使用Vue不被Vue所奴役,學(xué)習(xí)一下Vue底層的基本原理。 Vue官網(wǎng)有一段這樣的介...

    luqiuwen 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<