最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

vue中是怎樣監(jiān)聽數(shù)組變化的

 更新時(shí)間:2020年10月24日 09:14:33   作者:ming1025  
這篇文章主要介紹了vue中是怎樣監(jiān)聽數(shù)組變化的,幫助大家更好的理解和學(xué)習(xí)vue,感興趣的朋友可以了解下

我們知道通過Object.defineProperty()劫持?jǐn)?shù)組為其設(shè)置getter和setter后,調(diào)用的數(shù)組的push、splice、pop等方法改變數(shù)組元素時(shí)并不會(huì)觸發(fā)數(shù)組的setter,這就會(huì)造成使用上述方法改變數(shù)組后,頁面上并不能及時(shí)體現(xiàn)這些變化,也就是數(shù)組數(shù)據(jù)變化不是響應(yīng)式的(對(duì)上述不了解的可以參考這篇文章)。但實(shí)際用vue開發(fā)時(shí),對(duì)于響應(yīng)式數(shù)組,使用push、splice、pop等方法改變數(shù)組時(shí),頁面會(huì)及時(shí)體現(xiàn)這種變化,那么vue中是如何實(shí)現(xiàn)的呢?

通過vue源碼可以看出,vue重寫了數(shù)組的push、splice、pop等方法。

// src/core/observer/array.js

// 獲取數(shù)組的原型Array.prototype,上面有我們常用的數(shù)組方法
const arrayProto = Array.prototype
// 創(chuàng)建一個(gè)空對(duì)象arrayMethods,并將arrayMethods的原型指向Array.prototype
export const arrayMethods = Object.create(arrayProto)

// 列出需要重寫的數(shù)組方法名
const methodsToPatch = [
 'push',
 'pop',
 'shift',
 'unshift',
 'splice',
 'sort',
 'reverse'
]
// 遍歷上述數(shù)組方法名,依次將上述重寫后的數(shù)組方法添加到arrayMethods對(duì)象上
methodsToPatch.forEach(function (method) {
 // 保存一份當(dāng)前的方法名對(duì)應(yīng)的數(shù)組原始方法
 const original = arrayProto[method]
 // 將重寫后的方法定義到arrayMethods對(duì)象上,function mutator() {}就是重寫后的方法
 def(arrayMethods, method, function mutator (...args) {
  // 調(diào)用數(shù)組原始方法,并傳入?yún)?shù)args,并將執(zhí)行結(jié)果賦給result
  const result = original.apply(this, args)
  // 當(dāng)數(shù)組調(diào)用重寫后的方法時(shí),this指向該數(shù)組,當(dāng)該數(shù)組為響應(yīng)式時(shí),就可以獲取到其__ob__屬性
  const ob = this.__ob__
  let inserted
  switch (method) {
   case 'push':
   case 'unshift':
    inserted = args
    break
   case 'splice':
    inserted = args.slice(2)
    break
  }
  if (inserted) ob.observeArray(inserted)
  // 將當(dāng)前數(shù)組的變更通知給其訂閱者
  ob.dep.notify()
  // 最后返回執(zhí)行結(jié)果result
  return result
 })
})

從上面可以看出array.js中重寫了數(shù)組的push、pop、shift、unshift、splice、sort、reverse七種方法,重寫方法在實(shí)現(xiàn)時(shí)除了將數(shù)組方法名對(duì)應(yīng)的原始方法調(diào)用一遍并將執(zhí)行結(jié)果返回外,還通過執(zhí)行ob.dep.notify()將當(dāng)前數(shù)組的變更通知給其訂閱者,這樣當(dāng)使用重寫后方法改變數(shù)組后,數(shù)組訂閱者會(huì)將這邊變化更新到頁面中。

重寫完數(shù)組的上述7種方法外,我們還需要將這些重寫的方法應(yīng)用到數(shù)組上,因此在Observer構(gòu)造函數(shù)中,可以看到在監(jiān)聽數(shù)據(jù)時(shí)會(huì)判斷數(shù)據(jù)類型是否為數(shù)組。當(dāng)為數(shù)組時(shí),如果瀏覽器支持__proto__,則直接將當(dāng)前數(shù)據(jù)的原型__proto__指向重寫后的數(shù)組方法對(duì)象arrayMethods,如果瀏覽器不支持__proto__,則直接將arrayMethods上重寫的方法直接定義到當(dāng)前數(shù)據(jù)對(duì)象上;當(dāng)數(shù)據(jù)類型為非數(shù)組時(shí),繼續(xù)遞歸執(zhí)行數(shù)據(jù)的監(jiān)聽。

// src/core/observer/index.js
export class Observer {
 ...
 constructor (value: any) {
  this.value = value
  this.dep = new Dep()
  this.vmCount = 0
  def(value, '__ob__', this)
  if (Array.isArray(value)) {
   if (hasProto) {
    protoAugment(value, arrayMethods)
   } else {
    copyAugment(value, arrayMethods, arrayKeys)
   }
   this.observeArray(value)
  } else {
   this.walk(value)
  }
 }
 ...
}
function protoAugment (target, src: Object) {
 /* eslint-disable no-proto */
 target.__proto__ = src
 /* eslint-enable no-proto */
}
function copyAugment (target: Object, src: Object, keys: Array<string>) {
 for (let i = 0, l = keys.length; i < l; i++) {
  const key = keys[i]
  def(target, key, src[key])
 }
}

經(jīng)過上述處理后,對(duì)于數(shù)組,當(dāng)我們調(diào)用其方法處理數(shù)組時(shí)會(huì)按照如下原型鏈來獲取數(shù)組方法:

對(duì)于響應(yīng)式數(shù)組,當(dāng)瀏覽器支持__proto__屬性時(shí),使用push等方法時(shí)先從其原型arrayMethods上尋找push方法,也就是重寫后的方法,處理之后數(shù)組的變化會(huì)通知到其訂閱者,更新頁面,當(dāng)在arrayMethods上查詢不到時(shí)會(huì)向上在Array.prototype上查詢;當(dāng)瀏覽器不支持__proto__屬性時(shí),使用push等方法時(shí)會(huì)先從數(shù)組自身上查詢,如果查詢不到會(huì)向上再Array.prototype上查詢。

對(duì)于非響應(yīng)式數(shù)組,當(dāng)使用push等方法時(shí)會(huì)直接從Array.prototype上查詢。

值得一提的是源碼中通過判斷瀏覽器是否支持__proto__來分別使用protoAugment和copyAugment 方法將重寫后的數(shù)組方法應(yīng)用到數(shù)組中,這是因?yàn)閷?duì)于IE10及以下的IE瀏覽器是不支持__proto__屬性的:

上述截圖參考于Vue源碼解析五——數(shù)據(jù)響應(yīng)系統(tǒng)

結(jié)論:

在將數(shù)組處理成響應(yīng)式數(shù)據(jù)后,如果使用數(shù)組原始方法改變數(shù)組時(shí),數(shù)組值會(huì)發(fā)生變化,但是并不會(huì)觸發(fā)數(shù)組的setter來通知所有依賴該數(shù)組的地方進(jìn)行更新,為此,vue通過重寫數(shù)組的某些方法來監(jiān)聽數(shù)組變化,重寫后的方法中會(huì)手動(dòng)觸發(fā)通知該數(shù)組的所有依賴進(jìn)行更新。

如果我的內(nèi)容能對(duì)你有所幫助,我就很開心啦!

以上就是vue中是怎樣監(jiān)聽數(shù)組變化的的詳細(xì)內(nèi)容,更多關(guān)于vue 監(jiān)聽數(shù)組變化的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評(píng)論

建昌县| 沈阳市| 临邑县| 营口市| 兰溪市| 罗源县| 南投县| 山西省| 保亭| 天镇县| 日照市| 澄江县| 二连浩特市| 莫力| 绥江县| 津市市| 湖州市| 泸定县| 临猗县| 云阳县| 渭源县| 承德市| 达尔| 南涧| 姜堰市| 拉孜县| 滁州市| 茂名市| 阜新市| 西乡县| 东阿县| 彰化市| 沐川县| 夏津县| 安宁市| 布拖县| 黔西县| 齐河县| 扶风县| 宜都市| 宣城市|