久久r热视频,国产午夜精品一区二区三区视频,亚洲精品自拍偷拍,欧美日韩精品二区

您的位置:首頁(yè)技術(shù)文章
文章詳情頁(yè)

詳解實(shí)現(xiàn)vue的數(shù)據(jù)響應(yīng)式原理

瀏覽:5日期:2022-10-09 18:42:54

這篇文章主要是給不了解或者沒接觸過(guò) vue 響應(yīng)式源碼的小伙伴們看的,其主要目的在于能對(duì) vue 的響應(yīng)式原理有個(gè)基本的認(rèn)識(shí)和了解,如果在面試中被問(wèn)到此類問(wèn)題,能夠知道面試官想讓你回答的是什么?「PS:文中如有不對(duì)的地方,歡迎小伙伴們指正」

響應(yīng)式的理解

響應(yīng)式顧名思義就是數(shù)據(jù)變化,會(huì)引起視圖的更新。這篇文章主要分析 vue2.0 中對(duì)象和數(shù)組響應(yīng)式原理的實(shí)現(xiàn),依賴收集和視圖更新我們留在下一篇文章分析。

在 vue 中,我們所說(shuō)的響應(yīng)式數(shù)據(jù),一般指的是數(shù)組類型和對(duì)象類型的數(shù)據(jù)。vue 內(nèi)部通過(guò) Object.defineProperty 方法對(duì)對(duì)象的屬性進(jìn)行劫持,數(shù)組則是通過(guò)重寫數(shù)組的方法實(shí)現(xiàn)的。下面我們就簡(jiǎn)單實(shí)現(xiàn)一下。

首先我們定義一個(gè)需要被攔截的數(shù)據(jù)

const vm = new Vue({ data () { return { count: 0, person: { name: ’xxx’ }, arr: [1, 2, 3] } }})let arrayMethodsfunction Vue (options) { // 這里只考慮對(duì) data 數(shù)據(jù)的操作 let data = options.data if (data) { data = this._data = typeof data === ’function’ ? data.call(this) : data } observer (data)}function observer(data) { if (typeof data !== ’object’ || data === null) { return data } if (data.__ob__) { // 存在 __ob__ 屬性,說(shuō)明已經(jīng)被攔截過(guò)了 return data } new Observer(data)}

這里的 arrayMethods、Observer 、 __ob__的實(shí)現(xiàn)和作用請(qǐng)繼續(xù)往下看

實(shí)現(xiàn) Observer 類

class Observer { constructor (data) { Object.defineProperty(data, ’__ob__’, { // 在 data 上定義 __ob__ 屬性,在數(shù)組劫持里需要用到 enumerable: false, // 不可枚舉 configurable: false, // 不可配置 value: this // 值是 Observer 實(shí)例 }) if (Array.isArray(data)) { // 對(duì)數(shù)組進(jìn)行攔截 data.__proto__ = arrayMethods // 原型繼承 this.observerArray(data) } else { // 對(duì)象進(jìn)行攔截 this.walk(data) } } walk (data) { const keys = Object.keys(data) for(let i = 0; i < keys.length; i++) { const key = keys[i] defineReactive(data, key, data[key]) } } observerArray (data) { // 攔截?cái)?shù)組中的每一項(xiàng) data.forEach(value => observer(value)) }}對(duì)象的攔截

對(duì)象的劫持需要注意的幾點(diǎn):

遍歷對(duì)象,如果值還是對(duì)象類型,需要重新調(diào)用 observer 觀測(cè)方法 如果設(shè)置的新值是對(duì)象類型,也需要被攔截

// 處理對(duì)象的攔截function defineReactive(data, key, value) { observer(value) // 如果 value 值仍是對(duì)象類型,需要遞歸劫持 Object.defineProperty(data, key, { get() { return value }, set(newValue){ if (newValue === value) return value = newValue observer(newValue) // 如果設(shè)置 newValue 值也是對(duì)象類型,需要被劫持 } })}數(shù)組的劫持

數(shù)組的劫持需要注意的幾點(diǎn):

數(shù)組是使用函數(shù)劫持(切片編程)的思想,對(duì)數(shù)據(jù)進(jìn)行攔截的 數(shù)組里新增加的值,如果是對(duì)象類型,也需要被重新攔截

const oldArrayPrototype = Array.prototypearrayMethods = Object.create(oldArrayPrototype)const methods = [’push’, ’pop’, ’shift’, ’unshift’, ’splice’, ’sort’, ’reverse’] // 能夠改變?cè)瓟?shù)組的方法methods.forEach(method => { arrayMethods[methods] = function (...args) { const result = oldArrayPrototype[methods].call(this, ...args) const ob = this.__ob__ // this 就是調(diào)用改方法的數(shù)組 let inserted; // 數(shù)組新增的項(xiàng)的集合,需要再對(duì)其進(jìn)行攔截 switch(methods) { case ’push’: case ’unshift’: inserted = args case ’splice’: inserted = args.slice(2) // 因?yàn)?splice 第二個(gè)參數(shù)后面的才是新增的 } if (inserted) { ob.observerArray(inserted) } return result }})原理總結(jié)

在面試中,如果我們需要手寫 vue 的響應(yīng)式原理,上面的代碼足矣。但是我們通過(guò)學(xué)習(xí) vue 的源碼,如果在面試中能夠給出以下加以總結(jié)性的回答更能得到面試官的青睞。

vue 2.0 源碼的響應(yīng)式原理:

因?yàn)槭褂昧诉f歸的方式對(duì)對(duì)象進(jìn)行攔截,所以數(shù)據(jù)層級(jí)越深,性能越差 數(shù)組不使用 Object.defineProperty 的方式進(jìn)行攔截,是因?yàn)槿绻麛?shù)組項(xiàng)太多,性能會(huì)很差 只有定義在 data 里的數(shù)據(jù)才會(huì)被攔截,后期我們通過(guò) vm.newObj = ’xxx’ 這種在實(shí)例上新增的方式新增的屬性是不會(huì)被攔截的 改變數(shù)組的索引和長(zhǎng)度,不會(huì)被攔截,因此不會(huì)引起視圖的更新 如果在 data 上新增的屬性和更改數(shù)組的索引、長(zhǎng)度,需要被攔截到,可以使用 $set 方法 可以使用 Object.freeze 方法來(lái)優(yōu)化數(shù)據(jù),提高性能,使用了此方法的數(shù)據(jù)不會(huì)被重寫 set 和 get 方法

vue 3.0 源碼響應(yīng)式原理:

3.0 版本中使用了 proxy 代替了 Object.defineProperty ,其有13中攔截方式,不需要對(duì)對(duì)象和數(shù)組分別進(jìn)行處理,也無(wú)需遞歸進(jìn)行攔截,這也是其提升性能最大的地方 vue 3.0 版本響應(yīng)式原理的簡(jiǎn)單實(shí)現(xiàn)

const handler = { get (target, key) { if (typeof target[key] === ’object’ && target[key] !== null) { return new Proxy(target[key], handler) } return Reflect.get(target, key) }, set (target, key, value) { if(key === ’length’) return true console.log(’update’) return Reflect.set(target, key, value) }}const obj = { arr: [1, 2, 3], count: { num: 1 }}// obj 是代理的目標(biāo)對(duì)象, handler 是配置對(duì)象const proxy = new Proxy(obj, handler)

到此這篇關(guān)于詳解實(shí)現(xiàn)vue的數(shù)據(jù)響應(yīng)式原理的文章就介紹到這了,更多相關(guān)vue 數(shù)據(jù)響應(yīng)式內(nèi)容請(qǐng)搜索好吧啦網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持好吧啦網(wǎng)!

標(biāo)簽: Vue
相關(guān)文章:
主站蜘蛛池模板: 云安县| 石阡县| 随州市| 永顺县| 志丹县| 宾川县| 宁晋县| 阿拉善盟| 寿阳县| 盐边县| 石渠县| 日照市| 永定县| 民县| 五家渠市| 射洪县| 门头沟区| 城步| 濮阳县| 和静县| 嵊泗县| 台中县| 正阳县| 务川| 海伦市| 东兴市| 威宁| 瑞丽市| 芦山县| 周至县| 宁陕县| 延边| 淳化县| 竹溪县| 沈阳市| 浑源县| 成安县| 共和县| 临高县| 罗山县| 泰来县|