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

VUE響應(yīng)式原理的實現(xiàn)詳解

 更新時間:2022年03月28日 15:09:05   作者:Vhome_99  
這篇文章主要為大家詳細介紹了VUE響應(yīng)式原理的實現(xiàn),文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助

前言

相信vue學習者都會發(fā)現(xiàn),vue使用起來上手非常方便,例如雙向綁定機制,讓我們實現(xiàn)視圖、數(shù)據(jù)層的快速同步,但雙向綁定機制實現(xiàn)的核心數(shù)據(jù)響應(yīng)的原理是怎么樣的呢,接下來讓我們開始介紹:

function observer(value) {

	//給所有傳入進來的data 設(shè)置一個__ob__對象 一旦value有__ob__ 說明該value已經(jīng)做了響應(yīng)式處理
	Object.defineProperty(value, '__ob__', {
		value: this, //當前實例 也就是new observer
		enumerable: false, //不可枚舉  即不可for in
		writable: true, // 可用賦值運算符改寫__ob__
		configurable: true //可改寫可刪除
	})

	//這里是判斷是對象 數(shù)組的話需要改造數(shù)組原型上的方法
	if (Object.prototype.toString.call(value) === "[object Array]") {
		//數(shù)組的話需要改造數(shù)組原型上的方法 下面會講解arrayMethods
		value.__proto__ = arrayMethods;
		//對數(shù)組進行響應(yīng)式處理
		observeArray(value);
	} else {
		//如果是對象 遍歷對象屬性進行響應(yīng)式處理
		iterate(value)
	}


}

// 遍歷對象屬性進行響應(yīng)式處理
function iterate(data) {
	const keys = Object.keys(data);
	keys.forEach((key) => {
		defineReactive(data, key, data[key])
	})
}

//響應(yīng)式處理 這里是核心
function defineReactive(data, key, value){
	//遞歸對象 這里是因為對象里面仍可能嵌套對象
	observe(value)

	//寫道這里 Object.defineProperty 我們主角出場了
 	// 這里實現(xiàn)了讀寫都能捕捉到,響應(yīng)式的底層原理
	Object.defineProperty(data, key, {
		get() { 
			console.log('我被成功訪問啦!');
			return value
		},
		set(newValue) { 
			if (newValue === value) return
			console.log("我被變更啦")
			value = newValue
		}
	})
}

function  observeArray(data) { 
	data.forEach(item => { 
		observe(item)
	})
}

function observe(value) {
    // 如果傳進來的是對象或者數(shù)組,則進行響應(yīng)式處理
    if (Object.prototype.toString.call(value) === '[object Object]' || Object.prototype.toString.call(value) === "[object Array]") {
        return new Observer(value)
    }
}

上面代碼簡單的實現(xiàn)了vue2.0中響應(yīng)式的原理,相信注釋也非常的清晰,總結(jié)一下三個主要的方法:

名稱作用
observer觀察者對象,對數(shù)組、對象進行響應(yīng)式處理
defineReactive攔截對象中的key中的set、get方法
observe響應(yīng)式處理的入口

從上面的大致實現(xiàn)方法中,我們不難看出幾個問題:

1.使用defineProperty,我們無法實現(xiàn)對象刪除的監(jiān)聽、以及新增對象屬性的時候,set方法沒有被調(diào)用,下圖是實驗結(jié)果

3.

在這里插入圖片描述

2.數(shù)組修改只能通過改寫的方法,無法通過arr[index] = xxx 進行修改,也無法通過length屬性進行修改,下圖是輸出結(jié)果:

在這里插入圖片描述

解決方案

針對上面的問題,vue提出了自己的解決方案:

$set(obj, key, value),原理相信大家不難猜出,通過hack的方式,對象的處理方法是重新為對象賦值,而數(shù)組是通過splice來轉(zhuǎn)換為響應(yīng)式

function set (target, key, val) {
  //isValidArrayIndex 用來檢測是否合法索引
  if (Array.isArray(target) && isValidArrayIndex(key)) {
    target.length = Math.max(target.length, key);
    target.splice(key, 1, val);
    return val
  }
  if (key in target && !(key in Object.prototype)) {
    target[key] = val;
    return val
  }
  //... 
  defineReactive$$1(ob.value, key, val);
  ob.dep.notify();
  return val
}

數(shù)組的特殊處理

相信大家還發(fā)現(xiàn),數(shù)組做了特殊處理,上面的代碼也寫到?jīng)]有使用遍歷使用defineProperty去監(jiān)聽數(shù)據(jù),修改數(shù)組原型上的部分方法,來實現(xiàn)修改數(shù)組觸發(fā)響應(yīng)式,也就是上面代碼的arrayMethods,我們接著來看這個的具體實現(xiàn)思路:

const arrayProto = Array.prototype
export const arrayMethods = Object.create(arrayProto)

const methodsToPatch = [
	'push',
	'pop',
	'shift',
	'unshift',
	'splice',
	'sort',
	'reverse'
]


methodsToPatch.forEach(method =>{
	// 緩存原來的方法
	def(arrayMethods, method)
})

function def(obj, key) {
	Object.defineProperties(obj, key, {
		enumerable: true,
		configurable: true,
		value: function (...args) {

			//獲取數(shù)組原生方法
			let original = arrayProto[key];

			//改變this指向 
			const result = original.apply(this, args)

			console.log('我被更新了');
			
			//result就是上文的arrayMethods
			return result;
		}
	})
}

這里大概分為三個思路

1.獲取數(shù)組原型上的方法

2.使用defineProperties對數(shù)組原型上的方法進行劫持

3.把需要被改造的 Array 原型方法指向改造后原型。

這樣做的好處

沒有直接修改 Array.prototype,而是直接把 arrayMenthods 賦值給 value 的 proto 。因為這樣不會污染全局的Array, arrayMenthods 只對 data中的Array 生效。

題外話

關(guān)于數(shù)組為什么不使用defineProperties進行劫持,網(wǎng)上大部分說法都是覺得開銷太大,因為在我們業(yè)務(wù)場景中一般的對象不會有太多屬性,但列表中幾千、上萬條數(shù)據(jù)確是很正常,這一點也可以講通。

總結(jié)

感謝你的閱讀,在vue3.0中使用proxy進行數(shù)據(jù)劫持后,都說解決了2.0存在的問題以及提升了效率,后面我也會完善3.0響應(yīng)式的實現(xiàn)原理。

本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!   

相關(guān)文章

  • 詳解vue3的沙箱機制

    詳解vue3的沙箱機制

    這篇文章主要介紹了vue3的沙箱機制的相關(guān)資料,幫助大家更好的理解和學習使用vue框架,感興趣的朋友可以了解下
    2021-04-04
  • vuejs如何清空表單數(shù)據(jù)、刪除對象中的空屬性公共方法

    vuejs如何清空表單數(shù)據(jù)、刪除對象中的空屬性公共方法

    這篇文章主要介紹了vuejs如何清空表單數(shù)據(jù)、刪除對象中的空屬性公共方法,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2025-03-03
  • 如何在vue中使用jsx語法

    如何在vue中使用jsx語法

    本文主要介紹了如何在vue中使用jsx語法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2022-07-07
  • 詳解elementUI中input框無法輸入的問題

    詳解elementUI中input框無法輸入的問題

    這篇文章主要介紹了詳解elementUI中input框無法輸入的問題,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-04-04
  • 詳解在vue-cli項目下簡單使用mockjs模擬數(shù)據(jù)

    詳解在vue-cli項目下簡單使用mockjs模擬數(shù)據(jù)

    這篇文章主要介紹了詳解在vue-cli項目下簡單使用mockjs模擬數(shù)據(jù),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-10-10
  • 詳解vuex中的this.$store.dispatch方法

    詳解vuex中的this.$store.dispatch方法

    這篇文章主要介紹了vuex中的this.$store.dispatch方法,必須要用commit(‘SET_TOKEN’,?tokenV)調(diào)用mutations里的方法,才能在store存儲成功,需要的朋友可以參考下
    2022-11-11
  • vue中的el-form表單rule校驗問題(特殊字符、中文、數(shù)字等)

    vue中的el-form表單rule校驗問題(特殊字符、中文、數(shù)字等)

    這篇文章主要介紹了vue中的el-form表單rule校驗問題(特殊字符、中文、數(shù)字等),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-05-05
  • elementui彈窗頁按鈕重復(fù)提交問題解決方法

    elementui彈窗頁按鈕重復(fù)提交問題解決方法

    本文主要介紹了elementui彈窗頁按鈕重復(fù)提交問題解決方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-08-08
  • vue中如何使用echarts和echarts-gl實現(xiàn)3D餅圖環(huán)形餅圖

    vue中如何使用echarts和echarts-gl實現(xiàn)3D餅圖環(huán)形餅圖

    現(xiàn)在vue是很多公司前端的主流框架,我目前所在公司接觸的項目也都是使用vue來實現(xiàn)的,很少有完全使用原生的JavaScript來寫項目的了,下面這篇文章主要給大家介紹了關(guān)于vue中如何使用echarts和echarts-gl實現(xiàn)3D餅圖環(huán)形餅圖的相關(guān)資料,需要的朋友可以參考下
    2023-03-03
  • vue3編寫帶提示的表格組件功能

    vue3編寫帶提示的表格組件功能

    本文介紹了如何使用Vue 3編寫一個帶提示的表格組件,并假設(shè)每行都有一個保存按鈕,如果需要全部保存,還會加上驗證,感興趣的朋友一起看看吧
    2025-02-02

最新評論

石首市| 合山市| 台前县| 海城市| 高台县| 东宁县| 兴国县| 万安县| 古蔺县| 蕉岭县| 小金县| 镇康县| 关岭| 临洮县| 广安市| 普宁市| 沾益县| 边坝县| 边坝县| 平南县| 许昌县| 屏东市| 兰州市| 鹤壁市| 武胜县| 迁安市| 嘉善县| 青海省| 资阳市| 洛南县| 丰城市| 疏勒县| 晋宁县| 乡宁县| 肥西县| 长寿区| 尚志市| 乐陵市| 会同县| 乡城县| 石嘴山市|