Vue2動(dòng)態(tài)添加屬性導(dǎo)致頁(yè)面不更新的原因與解決方案
一、問(wèn)題示例
我們先來(lái)看一個(gè)簡(jiǎn)單的例子:
<div id="app">
<p v-for="(value, key) in item" :key="key">
{{ value }}
</p>
<button @click="addProperty">動(dòng)態(tài)添加新屬性</button>
</div>
Vue 實(shí)例代碼如下:
const app = new Vue({
el: "#app",
data: () => ({
item: {
oldProperty: "舊屬性"
}
}),
methods: {
addProperty() {
this.item.newProperty = "新屬性"; // 動(dòng)態(tài)添加新屬性
console.log(this.item); // 數(shù)據(jù)確實(shí)更新了
}
}
});
點(diǎn)擊按鈕后,console 能打印出帶有 newProperty 的對(duì)象,但頁(yè)面上并沒(méi)有新增一行。
二、原理分析
為什么會(huì)出現(xiàn)這種情況?
Vue2 的響應(yīng)式系統(tǒng)是基于 Object.defineProperty 實(shí)現(xiàn)的。
const obj = {};
let val = "初始值";
Object.defineProperty(obj, "foo", {
get() {
console.log(`get foo: ${val}`);
return val;
},
set(newVal) {
if (newVal !== val) {
console.log(`set foo: ${newVal}`);
val = newVal;
}
}
});
當(dāng)訪問(wèn)或修改 foo 時(shí),會(huì)觸發(fā) getter/setter。但如果直接新增屬性:
obj.bar = "新屬性";
此時(shí) bar 并沒(méi)有通過(guò) Object.defineProperty 設(shè)置攔截,因此不是響應(yīng)式屬性。
這正是 Vue2 無(wú)法檢測(cè)到新屬性的原因。
三、解決方案
Vue2 不允許在已創(chuàng)建的實(shí)例上直接新增響應(yīng)式屬性,但我們有幾種方式來(lái)解決:
1. 使用 Vue.set()
Vue.set(this.item, "newProperty", "新屬性");
這樣 Vue 會(huì)調(diào)用內(nèi)部的 defineReactive,為新屬性建立響應(yīng)式綁定,并觸發(fā)視圖更新。
簡(jiǎn)化源碼邏輯如下:
function set(target, key, val) {
defineReactive(target, key, val);
dep.notify(); // 通知視圖更新
return val;
}
2. 使用 Object.assign()
直接使用 Object.assign() 并不能觸發(fā)更新,但如果創(chuàng)建一個(gè)新對(duì)象賦值給原對(duì)象,就可以:
this.item = Object.assign({}, this.item, { newProperty: "新屬性" });
這種方式適合一次性添加多個(gè)屬性。
3. 使用 $forceUpdate()
強(qiáng)制讓 Vue 實(shí)例重新渲染:
this.item.newProperty = "新屬性"; this.$forceUpdate();
不過(guò),這種方式不推薦,因?yàn)榇蠖鄶?shù)情況下說(shuō)明代碼結(jié)構(gòu)存在問(wèn)題。
四、小結(jié)
- 少量新增屬性 → 使用
Vue.set()。 - 大量新增屬性 → 使用
Object.assign()創(chuàng)建新對(duì)象。 - 臨時(shí)解決方案 → 使用
$forceUpdate()強(qiáng)制刷新(不建議)。
需要注意的是:Vue3 使用 Proxy 實(shí)現(xiàn)響應(yīng)式,可以直接動(dòng)態(tài)添加屬性,依然能觸發(fā)更新,不再存在這個(gè)問(wèn)題。
到此這篇關(guān)于Vue2動(dòng)態(tài)添加屬性導(dǎo)致頁(yè)面不更新的原因與解決方案的文章就介紹到這了,更多相關(guān)Vue2動(dòng)態(tài)添加屬性頁(yè)面不更新內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Vue.js實(shí)現(xiàn)輸入框清空功能的兩種方式
Vue.js 是一個(gè)流行的前端框架,它提供了多種方法來(lái)實(shí)現(xiàn)數(shù)據(jù)的雙向綁定和事件處理,在構(gòu)建表單時(shí),我們經(jīng)常需要實(shí)現(xiàn)清空輸入框的功能,本文將介紹兩種在Vue中實(shí)現(xiàn)輸入框清空功能的方法,感興趣的小伙伴跟著小編一起來(lái)看看吧2024-12-12
vue?3.0使用element-plus按需導(dǎo)入方法以及報(bào)錯(cuò)解決
Vue3是不能直接使用Element-ui了,需要換成Element-plus,下面這篇文章主要給大家介紹了關(guān)于vue?3.0使用element-plus按需導(dǎo)入方法以及報(bào)錯(cuò)解決的相關(guān)資料,需要的朋友可以參考下2024-02-02
Vue中watch監(jiān)聽(tīng)屬性新舊值相同的問(wèn)題解決方案
這篇文章主要給大家分享了Vue中watch監(jiān)聽(tīng)屬性新舊值相同問(wèn)題解決方案,如果有遇到相同問(wèn)題的朋友,可以參考閱讀本文2023-08-08
vue修改swiper框架輪播圖小圓點(diǎn)的樣式不起作用的解決
這篇文章主要介紹了vue修改swiper框架輪播圖小圓點(diǎn)的樣式不起作用的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-04-04

