vue 的 $set 方法用于解決對象屬性新增或數(shù)組元素變化時無法觸發(fā)響應(yīng)式更新的問題。當(dāng)直接給對象添加新屬性或通過索引修改數(shù)組項時,vue 無法自動追蹤這些變化,因此需要使用 $set 手動通知 vue 這些數(shù)據(jù)是響應(yīng)式的。1. 對于對象,若在初始化后添加新屬性(如 this.user.age = 20),該屬性不會自動成為響應(yīng)式,需用 this.$set(this.user, ‘age’, 20) 來設(shè)置;2. 對于數(shù)組,通過索引直接賦值(如 this.items[1] = newvalue)不會觸發(fā)更新,應(yīng)使用 this.$set(this.items, 1, newvalue) 或變異方法;3. 在嵌套對象或數(shù)組中,$set 也可用于設(shè)置深層屬性為響應(yīng)式,如 this.$set(this.obj, ‘deepkey’, { value: 1 })。需要注意的是,$set 只能在 vue 實例內(nèi)部使用,且建議在 data 中提前定義好結(jié)構(gòu)以避免依賴 $set。
Vue 的 $set 方法主要是為了解決它無法自動檢測對象屬性新增或數(shù)組元素變化的問題。
我們知道 Vue 是響應(yīng)式的,但這種響應(yīng)式是有前提的。對于對象來說,只有在初始化時就存在的屬性,Vue 才會進行 getter/setter 的劫持,從而實現(xiàn)數(shù)據(jù)的響應(yīng)式更新。如果我們在之后給對象添加新的屬性,Vue 就無法自動追蹤這個新屬性的變化,也就不會觸發(fā)視圖更新。這時候就需要用 $set 來手動通知 Vue 這個屬性是響應(yīng)式的。
對象新增屬性無法被 Vue 檢測
這是最常見的一種情況。比如:
立即學(xué)習(xí)“前端免費學(xué)習(xí)筆記(深入)”;
data() { return { user: { name: 'Tom' } } }
如果你直接寫:
this.user.age = 20;
雖然 user.age 被賦值了,但這個 age 屬性不是響應(yīng)式的,頁面上使用到的地方不會更新。
解決辦法就是用 $set:
this.$set(this.user, 'age', 20);
這樣 Vue 就知道你要給 user 添加一個響應(yīng)式的 age 屬性,并且會在數(shù)據(jù)變化時更新視圖。
數(shù)組索引修改不能觸發(fā)更新
Vue 對數(shù)組的變異方法做了封裝(如 push、pop、splice 等),這些方法可以觸發(fā)視圖更新。但如果你通過索引直接修改數(shù)組項,就不會觸發(fā)更新:
this.items[1] = newValue;
這行代碼雖然改了值,但 Vue 不會感知到。這時也應(yīng)該用 $set:
this.$set(this.items, 1, newValue);
或者也可以使用 splice 方法達到類似效果,但 $set 更直觀一些。
響應(yīng)式嵌套對象或數(shù)組時也適用
如果你有一個深層嵌套的對象或數(shù)組,需要設(shè)置某個深層屬性為響應(yīng)式,同樣可以用 $set。例如:
this.$set(this.obj, 'deepKey', { value: 1 });
甚至還可以鏈式調(diào)用多次 $set 來處理更復(fù)雜的結(jié)構(gòu)。
需要注意的是:
- $set 只能在 Vue 實例內(nèi)部使用,也就是組件中。
- 如果你已經(jīng)知道對象結(jié)構(gòu),最好在 data 中提前定義好初始值,這樣就不需要用 $set 了。
基本上就這些。總結(jié)來說,$set 主要是用來“提醒” Vue 某些數(shù)據(jù)需要變成響應(yīng)式的,因為 Vue 自己檢測不到。不復(fù)雜但容易忽略,特別是在動態(tài)修改對象和數(shù)組的時候。