欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

vue視圖響應(yīng)式更新詳細(xì)介紹

 更新時(shí)間:2022年09月16日 09:42:18   作者:super_wanan  
這篇文章主要介紹了Vue響應(yīng)式原理,響應(yīng)式就是當(dāng)對(duì)象本身(對(duì)象的增刪值)或者對(duì)象屬性(重新賦值)發(fā)生了改變的時(shí)候,就會(huì)運(yùn)行一些函數(shù),最常見(jiàn)的示render函數(shù)

概述

前面兩篇文章已經(jīng)實(shí)現(xiàn)了對(duì)數(shù)據(jù)的變化的監(jiān)聽(tīng)以及模板語(yǔ)法編譯初始化,但是當(dāng)數(shù)據(jù)變化時(shí),視圖還不能夠跟隨數(shù)據(jù)實(shí)時(shí)更新。本文就在之前的基礎(chǔ)上介紹下視圖響應(yīng)式更新部分。

思路

統(tǒng)一封裝更新函數(shù)

待數(shù)據(jù)發(fā)生改變時(shí)調(diào)用對(duì)應(yīng)的更新函數(shù)

這里思考個(gè)問(wèn)題:

在何時(shí)注冊(cè)這個(gè)更新函數(shù)?

如何找到對(duì)應(yīng)的更新函數(shù)?

第一步統(tǒng)一封裝更新函數(shù)

基于上篇文章compile的部分,將數(shù)據(jù)初始化的部分統(tǒng)一封裝起來(lái)。

compileText (n) {
    // 獲取表達(dá)式
    // n.textContent = this.$vm[RegExp.$1]
    // n.textContent = this.$vm[RegExp.$1.trim()]
    this.update(n, RegExp.$1.trim(), 'text')
  }
  text (node, exp) {
    this.update(node, exp, 'text')
    // node.textContent = this.$vm[exp] || exp
  }
  html (node, exp) {
    this.update(node, exp, 'html')
    // node.innerHTML = this.$vm[exp]
  }

很容易寫(xiě)出update方法:

每個(gè)指令都有對(duì)應(yīng)的[dir]Updater管理器,用于在公共的update函數(shù)里調(diào)用去在相應(yīng)視圖渲染數(shù)據(jù)。

  update (node, exp, dir) {
    // 第一步: 初始化值
    const fn = this[dir + 'Updater']
    fn && fn(node, this.$vm[exp])
  }
  textUpdater (node, val) {
    node.textContent = val
  }
  htmlUpdater (node, val) {
    node.innerHTML = val
  }

第二步監(jiān)聽(tīng)并觸發(fā)視圖更新

分析可知,每個(gè)模板渲染初始化的過(guò)程都需要對(duì)數(shù)據(jù)進(jìn)行監(jiān)聽(tīng),并注冊(cè)監(jiān)聽(tīng)函數(shù),因此在上述的update函數(shù)中添加更新邏輯。

  update (node, exp, dir) {
    // 第一步: 初始化值
    const fn = this[dir + 'Updater']
    fn && fn(node, this.$vm[exp])
    // 第二步: 更新
    new Watcher(this.$vm, exp, val => {
      fn && fn(node, val)
    })
  }

創(chuàng)建Watcher類(lèi):

// 監(jiān)聽(tīng)器:負(fù)責(zé)依賴(lài)更新
class Watcher {
  constructor (vm, key, updateFn) {
    this.vm = vm
    this.key = key
    this.updateFn = updateFn
  }
  update () {
    // 綁定作用域?yàn)閠his.vm,并且將this.vm[this.key]作為值傳進(jìn)去
    this.updateFn.call(this.vm, this.vm[this.key])
  }
}

此時(shí)我們已經(jīng)完成了更新函數(shù)的功能,需要做的就是在數(shù)據(jù)發(fā)生改變的時(shí)候,主動(dòng)調(diào)用下對(duì)應(yīng)的update函數(shù)。

簡(jiǎn)單測(cè)試下:聲明一個(gè)全局的watchers數(shù)組。在每次Watcher的構(gòu)造函數(shù)中都往watchers中push一下,那么我們就可以再Object.defineProperty()的set方法中去遍歷所有的watchers,調(diào)用update方法。

淺試一下:

const watchers = []
class Watcher {
  constructor (vm, key, updateFn) {
    this.vm = vm
    this.key = key
    this.updateFn = updateFn
    watchers.push(this)
  }
  update () {
    this.updateFn.call(this.vm, this.vm[this.key])
  }
}
function defineReactive (obj, key, val) {
  // 遞歸
  // val如果是個(gè)對(duì)象,就需要遞歸處理
  observe(val)
  const dep = new Dep()
  Object.defineProperty(obj, key, {
    get () {
      Dep.target && dep.addDep(Dep.target)
      return val
    },
    set (newVal) {
      if (newVal !== val) {
        val = newVal
        // 新值如果是對(duì)象,仍然需要遞歸遍歷處理
        observe(newVal)
        //暴力的寫(xiě)法,讓一個(gè)人干事指揮所有人動(dòng)起來(lái)(不管你需不需要更新,全給我更新一遍)
        watchers.forEach(watch => {
           watch.update()
        })
      }
    }
  })
}

此時(shí)頁(yè)面視圖已經(jīng)可以根據(jù)數(shù)據(jù)的變而發(fā)生相應(yīng)的更新了。

引入Dep管家

只觸發(fā)需要更新的函數(shù)

上述的寫(xiě)法過(guò)于暴力,數(shù)據(jù)量一旦稍微大點(diǎn)就會(huì)嚴(yán)重影響性能。vue內(nèi)部引入了Dep這個(gè)大管家的概念來(lái)進(jìn)行依賴(lài)收集,統(tǒng)一管理所有的watcher。只讓需要干活的watcher去update。

class Dep {
  constructor () {
    this.deps = []
  }
  addDep (dep) {
    this.deps.push(dep)
  }
  notify () {
    this.deps.forEach(dep => dep.update())
  }
}

每個(gè)data中的key對(duì)應(yīng)一個(gè)dep就行,所以選擇在Object.defineProperty的getter函數(shù)中進(jìn)行依賴(lài)收集。在watcher中觸發(fā)依賴(lài)收集

class Watcher {
  constructor (vm, key, updateFn) {
    this.vm = vm
    this.key = key
    this.updateFn = updateFn
    // 觸發(fā)依賴(lài)收集,使用一個(gè)靜態(tài)變量target去保存對(duì)應(yīng)的Watcher
    Dep.target = this
    // 主動(dòng)訪問(wèn)vm[key],觸發(fā)一下getter
    this.vm[this.key]
    Dep.target = null
  }
  update () {
    // 綁定作用域?yàn)閠his.vm,并且將this.vm[this.key]作為值傳進(jìn)去
    this.updateFn.call(this.vm, this.vm[this.key])
  }
}

收集依賴(lài),創(chuàng)建Dep實(shí)例

function defineReactive (obj, key, val) {
  observe(val)
  const dep = new Dep()
  Object.defineProperty(obj, key, {
    get () {
      Dep.target && dep.addDep(Dep.target)
      return val
    },
    set (newVal) {
      if (newVal !== val) {
        val = newVal
        observe(newVal)
        dep.notify()
      }
    }
  })
}

至此,我們一個(gè)簡(jiǎn)版的Vue就實(shí)現(xiàn)了。這里還沒(méi)有涉及到虛擬dom得概念,以后介紹。

實(shí)現(xiàn)下語(yǔ)法糖v-model

v-model雖然很像使用了雙向數(shù)據(jù)綁定的 Angular 的 ng-model,但是 Vue 是單項(xiàng)數(shù)據(jù)流,v-model 只是語(yǔ)法糖而已。

// 最簡(jiǎn)形式,省略了value的顯式綁定,省略了oninput的顯式事件監(jiān)聽(tīng),是第二句代碼的語(yǔ)法糖形式
<input v-model="sth" />
<input v-bind:value="sth" v-on:input="sth = $event.target.value" />
//第二句代碼的簡(jiǎn)寫(xiě)形式
<input :value="sth" @input="sth = $event.target.value" />

分析一下其就是在內(nèi)部實(shí)現(xiàn)了v-bind:value=“” 和@input。

 model (node, exp) {
   node.value = this.$vm[exp]
   node.addEventListener('input', (e) => {
     this.$vm[exp] = e.target.value
   })
 }

到此這篇關(guān)于vue視圖響應(yīng)式更新詳細(xì)介紹的文章就介紹到這了,更多相關(guān)vue響應(yīng)式更新內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Vue中子組件向父組件傳值以及.sync修飾符詳析

    Vue中子組件向父組件傳值以及.sync修飾符詳析

    .sync?修飾符所提供的功能,當(dāng)一個(gè)子組件改變了一個(gè)prop的值時(shí),這個(gè)變化也會(huì)同步到父組件中所綁定,下面這篇文章主要給大家介紹了關(guān)于Vue中子組件向父組件傳值以及.sync修飾符的相關(guān)資料,需要的朋友可以參考下
    2022-11-11
  • vue如何關(guān)閉prettier警告warn

    vue如何關(guān)閉prettier警告warn

    這篇文章主要介紹了vue如何關(guān)閉prettier警告warn問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-03-03
  • Vue Element前端應(yīng)用開(kāi)發(fā)之前端API接口的封裝

    Vue Element前端應(yīng)用開(kāi)發(fā)之前端API接口的封裝

    對(duì)整個(gè)系統(tǒng)來(lái)說(shuō),一般會(huì)有很多業(yè)務(wù)對(duì)象,而每個(gè)業(yè)務(wù)對(duì)象的API接口又有很多。我們這個(gè)VUE+Element 前端應(yīng)用就是針對(duì)ABP框架的業(yè)務(wù)對(duì)象,因此前端的業(yè)務(wù)對(duì)象接口也是比較統(tǒng)一的,那么可以考慮在前端中對(duì)后端API接口調(diào)用進(jìn)行封裝,引入ES6的方式進(jìn)行前端API的抽象簡(jiǎn)化。
    2021-05-05
  • vue實(shí)現(xiàn)Input輸入框模糊查詢(xún)方法

    vue實(shí)現(xiàn)Input輸入框模糊查詢(xún)方法

    這篇文章主要為大家詳細(xì)介紹了vue實(shí)現(xiàn)Input輸入框模糊查詢(xún)方法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-10-10
  • Vue.prototype詳解及使用方式

    Vue.prototype詳解及使用方式

    這篇文章主要介紹了Vue.prototype詳解及使用方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-03-03
  • Vue3 + Vue-PDF 實(shí)現(xiàn)PDF 文件在線預(yù)覽實(shí)戰(zhàn)

    Vue3 + Vue-PDF 實(shí)現(xiàn)PDF 文件在線預(yù)覽實(shí)戰(zhàn)

    這篇文章主要介紹了Vue3 + Vue-PDF 實(shí)現(xiàn)PDF 文件在線預(yù)覽實(shí)戰(zhàn),文章圍繞主題展開(kāi)詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下
    2022-06-06
  • vue 彈窗時(shí) 監(jiān)聽(tīng)手機(jī)返回鍵關(guān)閉彈窗功能(頁(yè)面不跳轉(zhuǎn))

    vue 彈窗時(shí) 監(jiān)聽(tīng)手機(jī)返回鍵關(guān)閉彈窗功能(頁(yè)面不跳轉(zhuǎn))

    這篇文章主要介紹了vue 彈窗時(shí) 監(jiān)聽(tīng)手機(jī)返回鍵關(guān)閉彈窗功能,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值(頁(yè)面不跳轉(zhuǎn)) ,需要的朋友可以參考下
    2019-05-05
  • 詳解vue跨組件通信的幾種方法

    詳解vue跨組件通信的幾種方法

    本篇文章主要介紹了詳解vue跨組件通信的幾種方法 ,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-06-06
  • 一定要知道的 25 個(gè) Vue 技巧

    一定要知道的 25 個(gè) Vue 技巧

    這篇文章主要給大家分享將 prop 限制為類(lèi)型列表、默認(rèn)內(nèi)容和擴(kuò)展點(diǎn)、使用引號(hào)觀察嵌套值、知道何時(shí)使用 v-if、單作用域 slot 的簡(jiǎn)寫(xiě)、有條件地渲染slot等25 個(gè)Vue 技巧,下文是下相關(guān)資料,需要的朋友可以參考一下
    2021-11-11
  • vue組件中的數(shù)據(jù)傳遞方法

    vue組件中的數(shù)據(jù)傳遞方法

    這篇文章主要介紹了vue組件中的數(shù)據(jù)傳遞方法,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2018-05-05

最新評(píng)論