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

深入探究Vue2響應(yīng)式原理的實(shí)現(xiàn)及存在的缺陷

 更新時(shí)間:2023年08月01日 09:26:11   作者:前端百草閣  
Vue的響應(yīng)式數(shù)據(jù)機(jī)制是其核心特性之一,它能夠自動(dòng)追蹤數(shù)據(jù)的變化,并實(shí)時(shí)更新相關(guān)的視圖,然而,Vue2中的響應(yīng)式數(shù)據(jù)機(jī)制并非完美無(wú)缺,本文將探討Vue2響應(yīng)式原理及其存在的缺陷

一、Vue2中的響應(yīng)式原理

  • Vue 2的響應(yīng)式原理:
    在Vue 2中,響應(yīng)式是通過(guò)使用Object.defineProperty()方法來(lái)實(shí)現(xiàn)的
    在組件實(shí)例化過(guò)程中,Vue會(huì)對(duì)數(shù)據(jù)對(duì)象(data)進(jìn)行遞歸地遍歷,將每個(gè)屬性都轉(zhuǎn)換為getter/setter,并且為每個(gè)屬性創(chuàng)建一個(gè)依賴追蹤的系統(tǒng)。當(dāng)屬性被訪問(wèn)或修改時(shí),getter/setter會(huì)觸發(fā)依賴追蹤系統(tǒng),從而進(jìn)行依賴收集派發(fā)更新,以保證數(shù)據(jù)和視圖的同步。
  • 具體實(shí)現(xiàn)步驟如下:
    1.創(chuàng)建Observer對(duì)象:通過(guò)遞歸地將data對(duì)象的屬性轉(zhuǎn)換為響應(yīng)式屬性,使用Object.defineProperty()為每個(gè)屬性添加getter和setter方法。Vue2中 通過(guò)使用 Object.defineProperty() 方法,將對(duì)象的屬性轉(zhuǎn)換成 getter 和 setter,當(dāng)數(shù)據(jù)發(fā)生變化時(shí),會(huì)自動(dòng)觸發(fā)相應(yīng)的更新函數(shù),實(shí)現(xiàn)數(shù)據(jù)的響應(yīng)式。
    2.創(chuàng)建Dep對(duì)象:用來(lái)管理 Watcher,它用來(lái)收集依賴、刪除依賴和向依賴發(fā)送消息等。用于解耦屬性的依賴收集和派發(fā)更新操作。
    3.創(chuàng)建Watcher對(duì)象:Watcher對(duì)象用于連接視圖和數(shù)據(jù)之間的橋梁,當(dāng)被依賴的屬性發(fā)生變化時(shí),Watcher對(duì)象會(huì)接收到通知并更新視圖。當(dāng)數(shù)據(jù)發(fā)生變化時(shí),它會(huì)通知訂閱該數(shù)據(jù)的組件更新視圖。Watcher 在實(shí)例化時(shí)會(huì)將自己添加到 Dep 中,當(dāng)數(shù)據(jù)發(fā)生變化時(shí),會(huì)觸發(fā)相應(yīng)的更新函數(shù)。
    4.模板編譯:Vue會(huì)解析模板,將模板中的數(shù)據(jù)綁定指令轉(zhuǎn)譯為對(duì)應(yīng)的更新函數(shù),以便在數(shù)據(jù)發(fā)生變化時(shí)調(diào)用。

在修改對(duì)象的值的時(shí)候,會(huì)觸發(fā)對(duì)應(yīng)的 setter, setter通知之前依賴收集得到的 Dep 中的Watcher,告訴它自己的值改變了,需要重新渲染視圖。這時(shí)候這些 Watcher就會(huì)開(kāi)始調(diào)用 update 來(lái)更新視圖, 對(duì)應(yīng)的getter觸發(fā)追蹤,把新值重新渲染到視圖上

input用v-model綁定數(shù)據(jù),我們需要在input元素上添加事件監(jiān)聽(tīng),每當(dāng)input事件被觸發(fā)時(shí),就修改對(duì)應(yīng)的data,data里的數(shù)據(jù)又會(huì)響應(yīng)式更新回視圖

二、模擬簡(jiǎn)易版響應(yīng)式原理

實(shí)現(xiàn)思路:
定義一個(gè)Observe構(gòu)造函數(shù)用于對(duì)data對(duì)象的屬性進(jìn)行數(shù)據(jù)劫持。我們使用Object.defineProperty()方法對(duì)data對(duì)象的每個(gè)屬性進(jìn)行劫持,定義了屬性的getter和setter方法。
在getter方法中,我們返回屬性的值。在setter方法中,我們判斷新值是否與舊值不同,如果不同,則更新屬性的值,并觸發(fā)依賴更新。

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8" />
		<title>Document</title>
	</head>
	<body>
		<script type="text/javascript" >
			let data = {
				name:'前端百草閣',
				age:21,
			}
			function Observer(obj){
				//匯總對(duì)象中所有的鍵形成一個(gè)數(shù)組
				const keys = Object.keys(obj)
				//遍歷
				keys.forEach((k)=>{
					Object.defineProperty(this,k,{
						get(){
							return obj[k]
						},
						set(val){
							console.log(`${k}被改了,我要通知Vue重新去解析模板.....`)
							obj[k] = val
						}
					})
				})
			}
			//創(chuàng)建一個(gè)監(jiān)視的實(shí)例對(duì)象,用于監(jiān)視data中屬性的變化
			const obs = new Observer(data)		
			//準(zhǔn)備一個(gè)vm實(shí)例對(duì)象
			let vm = {}
			vm._data = data = obs
		</script>
	</body>
</html>

這個(gè)時(shí)候,原先data里的屬性就會(huì)各自有一個(gè)為他們服務(wù)的getter和setter,變成了具有響應(yīng)式的屬性

  • 簡(jiǎn)易式版本的缺陷
    • 缺陷一:正常vue中會(huì)做一個(gè)數(shù)據(jù)代理,當(dāng)訪問(wèn)vm.name時(shí),訪問(wèn)的其實(shí)是vm._data.name,這樣做了數(shù)據(jù)代理后使用起來(lái)更方便

  • 缺陷二: 簡(jiǎn)易式版本沒(méi)有考慮到data里面的屬性值還是對(duì)象的情況,在Vue中利用遞歸的方法將data里所有的屬性通過(guò)遞歸的方式都轉(zhuǎn)換為了響應(yīng)式屬性(即使屬性值是一個(gè)數(shù)組,數(shù)組里藏了對(duì)象,依然可以把對(duì)應(yīng)的屬性轉(zhuǎn)換為響應(yīng)式屬性)

這里有一個(gè)小tips,利用this指向obs,訪問(wèn)this(obs)里的屬性,getter返回的其實(shí)是obj里的屬性(數(shù)據(jù)代理),為什么要這樣呢?如果說(shuō)你訪問(wèn)obj里的屬性,我真的通過(guò)getter給你返回了obj里對(duì)應(yīng)的屬性,返回的obj里的屬性又要去觸發(fā)自己的getter,那是不是就陷入死循環(huán)了呢?導(dǎo)致的問(wèn)題就是無(wú)論你是觸發(fā)getter 還是setter都會(huì)導(dǎo)致超出最大調(diào)用堆棧這個(gè)錯(cuò)誤

解決這個(gè)問(wèn)題還有一個(gè)辦法就是利用閉包,利用閉包把初始值傳給value存起來(lái)了,后續(xù)getter和setter都是針對(duì)閉包內(nèi)的value,和原本的obj隔離開(kāi)了,當(dāng)你訪問(wèn)或者設(shè)置obj.key的時(shí)候,就會(huì)去修改對(duì)應(yīng)的val(由于閉包val不會(huì)被垃圾機(jī)制回收)就不存在最大調(diào)用堆棧溢出的情況了

function observe(obj) {
  if (!obj || typeof obj !== 'object') {
    return;
  }
  Object.keys(obj).forEach(function(key) {
    defineReactive(obj, key, obj[key]); 
  });
}
function defineReactive(obj, key, val) {
  observe(val);  // 遞歸地對(duì)data對(duì)象的屬性進(jìn)行數(shù)據(jù)劫持
  Object.defineProperty(obj, key, {
    get: function() {
      return val;
    },
    set: function(newValue) {
      if (newValue !== val) {
        val = newValue;
        // 觸發(fā)依賴更新
        updateView();
      }
    }
  });
}
function updateView() {
  document.querySelector('h1').innerText = vm.message;
}
// 初始化數(shù)據(jù)劫持
observe(vm.$data);

在上述代碼中,observe函數(shù)用于遞歸地對(duì)data對(duì)象的屬性進(jìn)行數(shù)據(jù)劫持。在defineReactive函數(shù)中,我們使用Object.defineProperty()方法對(duì)data對(duì)象的每個(gè)屬性進(jìn)行劫持,定義了屬性的getter和setter方法。
在getter方法中,我們返回屬性的值。在setter方法中,我們判斷新值是否與舊值不同,如果不同,則更新屬性的值,并觸發(fā)依賴更新。
最后,我們調(diào)用observe(vm.$data)來(lái)初始化數(shù)據(jù)劫持,使得Vue能夠捕獲到對(duì)data對(duì)象屬性的訪問(wèn)和修改操作,并觸發(fā)相應(yīng)的依賴更新。

三、Vue2響應(yīng)式數(shù)據(jù)帶來(lái)的缺陷

Vue 2中的響應(yīng)式數(shù)據(jù)存在一些缺陷,但通過(guò)使用Vue提供的補(bǔ)救辦法,可以解決大部分響應(yīng)式數(shù)據(jù)的問(wèn)題。

3.1 新增屬性的響應(yīng)問(wèn)題

Vue在初始化時(shí)會(huì)對(duì)data對(duì)象的屬性進(jìn)行數(shù)據(jù)劫持,但是對(duì)于后續(xù)新增的屬性,Vue無(wú)法自動(dòng)進(jìn)行響應(yīng)式處理。
Vue 無(wú)法探測(cè)普通的新增屬性 ,比如 this.myObject.saying = 'hi',這個(gè)新增的saying屬性是不具有響應(yīng)式的,Vue探測(cè)不到

3.2 數(shù)組變動(dòng)的響應(yīng)問(wèn)題

Vue對(duì)數(shù)組的變動(dòng)(例如通過(guò)索引修改數(shù)組元素、通過(guò)splice方法刪除或插入元素)無(wú)法直接進(jìn)行響應(yīng)式處理。

例如此時(shí)在data里定義了這些數(shù)據(jù)

data:{
		friends:[
			{name:'jerry',age:35},
			{name:'tony',age:36},
			'前端百草閣'
		]
	}

不難發(fā)現(xiàn)數(shù)組中的對(duì)象都是響應(yīng)式的,但數(shù)組中的普通元素卻不是響應(yīng)式的,意味著若直接修改數(shù)組中的元素Vue無(wú)法監(jiān)測(cè)到

如果你通過(guò)數(shù)組下標(biāo)修改對(duì)象屬性的話是可以監(jiān)測(cè)的,因?yàn)閷?duì)象里的屬性都是響應(yīng)式的,但如果你通過(guò)數(shù)組下標(biāo)修改普通元素是無(wú)法監(jiān)測(cè)到的

如果用一個(gè)新數(shù)組覆蓋掉原先的數(shù)組,Vue是能監(jiān)測(cè)到的

3.3 對(duì)象屬性的刪除問(wèn)題

Vue無(wú)法直接檢測(cè)到對(duì)象屬性的刪除操作。
利用delete刪除對(duì)象的屬性,無(wú)法被Vue監(jiān)測(cè)到

四、Vue2響應(yīng)式缺陷的解決辦法

4.1 新增屬性的響應(yīng)問(wèn)題

Vue.set( target, propertyName/index, value )

向響應(yīng)式對(duì)象中添加一個(gè) property,并確保這個(gè)新 property 同樣是響應(yīng)式的,且觸發(fā)視圖更新。它必須用于向響應(yīng)式對(duì)象上添加新 property,因?yàn)?Vue 無(wú)法探測(cè)普通的新增 property (比如 this.myObject.newProperty = ‘hi’)

給data中的student對(duì)象添加一個(gè)屬性,并且是響應(yīng)式的,有兩種寫(xiě)法,Vue.set或者this.$set

// Vue.set(this._data.student,'sex','男') // 這里加不加_data實(shí)際上都可以,就是一個(gè)數(shù)據(jù)代理,訪問(wèn)誰(shuí)都一樣,那我們肯定選擇偷懶啦
this.$set(this.student,'sex','男')  // this代表vm vue實(shí)例對(duì)象

實(shí)現(xiàn)了新增了student對(duì)象里的sex屬性,并且該屬性有為自己服務(wù)的getter、setter(具有響應(yīng)式)

但是,Vue官網(wǎng)明確指出:注意對(duì)象不能是 Vue 實(shí)例,或者 Vue 實(shí)例的根數(shù)據(jù)對(duì)象。
簡(jiǎn)單來(lái)說(shuō)就是,set方法的第一個(gè)參數(shù)target不允許 是vm(vue實(shí)例)、也不允許是vm._data(根數(shù)據(jù)對(duì)象)

4.2 數(shù)組變動(dòng)的響應(yīng)問(wèn)題

第一中解決辦法,使用數(shù)組變異方法:Vue提供了一些數(shù)組變異方法(例如push、pop、shift、unshift、splice、sort和reverse),這些方法會(huì)觸發(fā)數(shù)組的響應(yīng)式更新。
如果不是這七個(gè)方法的話,比如調(diào)用slice等數(shù)組方法的話,記得要把返回的新數(shù)組覆蓋掉原來(lái)的舊數(shù)組,依然能觸發(fā)響應(yīng)式

第二種解決辦法,利用set方法,set方法不但能解決對(duì)象新增屬性的問(wèn)題,還能解決修改數(shù)組的問(wèn)題(用的不多)

4.3 對(duì)象屬性的刪除問(wèn)題

Vue.delete方法:用來(lái)刪除對(duì)象的屬性,并觸發(fā)響應(yīng)式更新。例如,可以使用Vue.delete(vm.someObject, ‘propertyToDelete’)來(lái)刪除一個(gè)屬性。
正常的delete方法,雖然確實(shí)刪除了屬性,但是無(wú)法被監(jiān)測(cè)到

利用Vue.delete完美解決刪除對(duì)象屬性無(wú)法被監(jiān)測(cè)的問(wèn)題(很少用到),或者vm.$delete(vm.person,'name')

總結(jié)

Vue 2的響應(yīng)式數(shù)據(jù)機(jī)制在大多數(shù)情況下能夠滿足我們的需求,但也存在一些缺陷。
首先,Vue無(wú)法直接響應(yīng)新增的屬性,需要使用特定的方法進(jìn)行補(bǔ)救。其次,對(duì)于數(shù)組的變動(dòng)和對(duì)象屬性的刪除,Vue也無(wú)法直接進(jìn)行響應(yīng)式處理,需要使用相應(yīng)的方法來(lái)觸發(fā)更新。這些缺陷在實(shí)際開(kāi)發(fā)中可能會(huì)帶來(lái)一些困擾。
但幸運(yùn)的是,Vue提供了一些補(bǔ)救的辦法,如Vue.set和Vue.delete方法,以及數(shù)組變異方法。通過(guò)這些補(bǔ)救措施,我們可以彌補(bǔ)Vue 2響應(yīng)式數(shù)據(jù)機(jī)制的不足,提升開(kāi)發(fā)效率和用戶體驗(yàn)。盡管如此,我們也期待Vue未來(lái)版本的改進(jìn),在響應(yīng)式數(shù)據(jù)方面能夠更加智能和靈活,以滿足更多復(fù)雜場(chǎng)景的需求。

以上就是深入探究Vue2響應(yīng)式原理的實(shí)現(xiàn)及存在的缺陷的詳細(xì)內(nèi)容,更多關(guān)于Vue2響應(yīng)式原理的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Vue中的Ajax?配置代理slot插槽的方法詳解

    Vue中的Ajax?配置代理slot插槽的方法詳解

    這篇文章主要介紹了Vue中的Ajax?配置代理?slot插槽的相關(guān)知識(shí),本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-06-06
  • vue中使用file-saver導(dǎo)出文件的全過(guò)程記錄

    vue中使用file-saver導(dǎo)出文件的全過(guò)程記錄

    這篇文章主要給大家介紹了關(guān)于vue中使用file-saver導(dǎo)出文件的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2022-02-02
  • Vue3警告:Failed to resolve component:XXX的詳細(xì)解決辦法

    Vue3警告:Failed to resolve component:XXX的詳細(xì)解決辦法

    最近在一個(gè)vue3項(xiàng)目中遇到了報(bào)錯(cuò),整理了些解決辦法,這篇文章主要給大家介紹了關(guān)于Vue3警告:Failed to resolve component:XXX的詳細(xì)解決辦法,文中介紹的非常詳細(xì),需要的朋友可以參考下
    2023-05-05
  • Vue 短信驗(yàn)證碼組件開(kāi)發(fā)詳解

    Vue 短信驗(yàn)證碼組件開(kāi)發(fā)詳解

    Vue.js(讀音 /vju&#720;/, 類似于 view)是一個(gè)構(gòu)建數(shù)據(jù)驅(qū)動(dòng)的 web 界面的庫(kù)。這篇文章主要介紹了Vue 短信驗(yàn)證碼組件開(kāi)發(fā)詳解,需要的朋友可以參考下
    2017-02-02
  • vue 中 get / delete 傳遞數(shù)組參數(shù)方法

    vue 中 get / delete 傳遞數(shù)組參數(shù)方法

    這篇文章主要介紹了vue 中 get / delete 傳遞數(shù)組參數(shù)方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-03-03
  • Vue 3 中的 toRef 和 toRefs 函數(shù)案例講解

    Vue 3 中的 toRef 和 toRefs 函數(shù)案例講解

    這篇文章主要介紹了Vue 3 中的 toRef 和 toRefs 函數(shù),toRef 和 toRefs 函數(shù)是 Vue 3 中的兩個(gè)非常有用的函數(shù),它們可以幫助我們更好地管理組件中的響應(yīng)式數(shù)據(jù),并且可以提高組件的性能和用戶體驗(yàn),需要的朋友可以參考下
    2024-06-06
  • 詳解IOS微信上Vue單頁(yè)面應(yīng)用JSSDK簽名失敗解決方案

    詳解IOS微信上Vue單頁(yè)面應(yīng)用JSSDK簽名失敗解決方案

    這篇文章主要介紹了詳解IOS微信上Vue單頁(yè)面應(yīng)用JSSDK簽名失敗解決方案,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-11-11
  • vue全局引入scss(mixin)

    vue全局引入scss(mixin)

    本文主要介紹了?vue全局引入scss,我們?cè)趯?xiě)VUE的時(shí)候,會(huì)使用scss,也會(huì)做一些通用樣式,方便使用,在寫(xiě)好的通用樣式的時(shí)候,每次都要單文件導(dǎo)入,剛開(kāi)始寫(xiě)的時(shí)候,感覺(jué)還好,后面工程量大了后,就顯得麻煩,那么本文就全局導(dǎo)入scss樣式,下面來(lái)看詳細(xì)內(nèi)容,需要的朋友可以參考一下
    2021-11-11
  • vue el-row中ul間距問(wèn)題

    vue el-row中ul間距問(wèn)題

    這篇文章主要介紹了vue el-row中ul間距問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-08-08
  • Vue的過(guò)濾器你真了解嗎

    Vue的過(guò)濾器你真了解嗎

    這篇文章主要為大家詳細(xì)介紹了Vue的過(guò)濾器,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助
    2022-02-02

最新評(píng)論

安乡县| 共和县| 哈巴河县| 潮州市| 潞西市| 三明市| 莱州市| 都昌县| 鄂尔多斯市| 罗田县| 荆州市| 抚顺县| 侯马市| 黑山县| 临潭县| 兴安县| 萝北县| 阿拉尔市| 碌曲县| 黔江区| 岳西县| 湟源县| 通许县| 阳城县| 梁平县| 安图县| 织金县| 故城县| 南江县| 深州市| 兰考县| 承德县| 临桂县| 大厂| 阜阳市| 巴青县| 平遥县| 怀远县| 六盘水市| 陈巴尔虎旗| 工布江达县|