色综合图-色综合图片-色综合图片二区150p-色综合图区-玖玖国产精品视频-玖玖香蕉视频

您的位置:首頁技術文章
文章詳情頁

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

瀏覽:104日期:2022-11-13 10:50:20

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

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

// src/core/observer/array.js// 獲取數(shù)組的原型Array.prototype,上面有我們常用的數(shù)組方法const arrayProto = Array.prototype// 創(chuàng)建一個空對象arrayMethods,并將arrayMethods的原型指向Array.prototypeexport const arrayMethods = Object.create(arrayProto)// 列出需要重寫的數(shù)組方法名const methodsToPatch = [ ’push’, ’pop’, ’shift’, ’unshift’, ’splice’, ’sort’, ’reverse’]// 遍歷上述數(shù)組方法名,依次將上述重寫后的數(shù)組方法添加到arrayMethods對象上methodsToPatch.forEach(function (method) { // 保存一份當前的方法名對應的數(shù)組原始方法 const original = arrayProto[method] // 將重寫后的方法定義到arrayMethods對象上,function mutator() {}就是重寫后的方法 def(arrayMethods, method, function mutator (...args) { // 調用數(shù)組原始方法,并傳入?yún)?shù)args,并將執(zhí)行結果賦給result const result = original.apply(this, args) // 當數(shù)組調用重寫后的方法時,this指向該數(shù)組,當該數(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) // 將當前數(shù)組的變更通知給其訂閱者 ob.dep.notify() // 最后返回執(zhí)行結果result return result })})

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

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

// src/core/observer/index.jsexport 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)過上述處理后,對于數(shù)組,當我們調用其方法處理數(shù)組時會按照如下原型鏈來獲取數(shù)組方法:

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

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

對于非響應式數(shù)組,當使用push等方法時會直接從Array.prototype上查詢。

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

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

結論:

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

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

以上就是vue中是怎樣監(jiān)聽數(shù)組變化的的詳細內(nèi)容,更多關于vue 監(jiān)聽數(shù)組變化的資料請關注好吧啦網(wǎng)其它相關文章!

標簽: Vue
相關文章:
主站蜘蛛池模板: 欧美一区二区三区在线观看 | 国产在线精品成人一区二区三区 | 久草在线免费资源站 | 在线满18网站观看视频 | 久久tv免费国产高清 | 国产精品露脸脏话对白 | 亚洲99久久久久综合 | 日韩国产三级 | 亚洲欧美人妖另类激情综合区 | 女人张开腿让男人桶个爽 | 亚洲综合第一页 | 美女又黄又免费 | 亚洲第一狼人区 | 久久r这里只有精品 | 国产成人综合网在线观看 | 性成人动作片在线看 | 久久久久久毛片免费播放 | 韩国一级特黄毛片大 | 国产成视频 | 亚洲福利影院 | a级毛片无码免费真人 | 乱系列中文字幕在线视频 | 麻豆日韩| 最新国产三级在线观看不卡 | 欧美视频一区二区在线观看 | 久草小视频| 长腿嫩模打开双腿呻吟 | 中文字幕日本不卡 | 在线免费看一级片 | 国产成人啪精品午夜在线观看 | 久久久久久久久久毛片精品美女 | 毛片手机在线 | 一级毛片美国一级j毛片不卡 | 久久久香蕉视频 | 国产综合精品一区二区 | 亚洲国产成人久久99精品 | 亚洲欧美国产中文 | 成年女人毛片免费观看中文w | 久久99久久精品免费思思6 | 成人三级做爰在线观看男女 | 国产精品资源手机在线播放 |