淺析如何保證vuex中的state動態添加屬性的響應式及解決deep watch / computed監聽vuex state對象屬性變化不生效的問題


一、vuex 的 state 如何保證其響應式

  vuex 的 store對象的 state 是響應式的,凡是預先在 state 中定義的狀態,都會被加入到響應式系統中,當狀態發生了變化,所有引用狀態的 vue 文件的 template 都會隨之發生變化,做到響應式的功能。

  但是其前提是:提前定義好的會被加入到響應式系統中,那后面追加的屬性或對象能不能加入到響應式系統中呢?

  答案是:不能,但是,如果按照指定的方式來添加和刪除屬性,是可以做到響應式的。

  比如現在我要添加一個新屬性 height,用兩種方式添加,如下:

1、方式1:此種方式能添加 state 中對象的屬性,但無法加入到響應式系統中,即頁面上不會顯示出來,實際上確實存在了這個屬性

mutations: {   addheight(state){     state.stus[0]['height'] = 168   } }

2、方式2:此方式可以讓屬性加入到響應式系統中

mutations: {   addheight(state){     Vue.set(state.stus[1],'height',178) //參數一為對象,參數二為key,參數為value
  } }

3、方式3:用新對象給舊對象重新賦值(下面會介紹到)

4、說完添加屬性,再說下刪除吧,想要刪除屬性並加入響應式系統,如下方式:

mutations: {   delheight(state){     Vue.delete(state.stus[1],'height') //參數一為對象,參數二是key
  } }

5、總結:

(1)Vuex 的 store 對象中的 state 是響應式的,當 state 中的數據發生改變時,vue 組件會自動更新。

(2)但是它有一個前提條件,與我們之前了解的響應式前提是一致的,就是需要:提前在 state 中定義好所需的初始化屬性。動態添加的屬性是不能響應式的。

(3)如何保證動態添加的屬性的響應式呢 - 有一下兩種方式

  方式一:使用 Vue.set(obj, key, value)

  方式二:使用新對象給舊對象重新賦值

(4)在state刪除已經存在的屬性,使用 delete + 屬性滿足不了響應式,必須這樣使用:Vue.delete(obj, 屬性名)

二、解決 computed 監聽 vuex 中 state 對象屬性不生效的問題

  首先我們需要了解一個前提基礎:

computed 屬性監聽對象時候,若對象的引用地址未改變,那么computed將不會檢測到。

比如object中的某個key對應的value發生了變化,computed檢測不出來

// 原寫法
export default { namespaced: true, state: { info:{ other: {} } }, mutations: { addInformation(state,info){ let data = Object.assign(state.info, info); //此時 state.info 的值改變了,但是引用地址沒變
            state.shareInformation = data; }, } }

  使用 Object.assign() 的目標對象仍然是 state.info ,所以雖然其值變了,但是引用地址是沒變的,所以 computed 檢測不到。

// 正確寫法
addInformation(state,info){   //創建一個新的對象,將state.info,Info 對象復制到新對象中
  let data = Object.assign({},state.info,info);   //將 state.info 指向新對象的引用地址
  state.info = data; },

  使用 Object.assign() 的目標對象是個空對象,將 2 個源對象 state.info、info 的內容復制到新對象上 ,所以其值變了,引用地址也變了。這樣 computed 才可以檢測到。

三、vue 關於 deep watch 監聽不到 vuex state 對象變化的的問題

  簡而言之,如果 vuex state 中是一個空對象 {},那么監聽就會有問題,必須得有提前定義好的初始化屬性才可以保證監聽。那么如果無法確定動態添加屬性的 key 是啥,怎么辦呢?先給出解決方案:

// 簡易拷貝
let _reply = JSON.parse(JSON.stringify(state.reply)) // 加入動態屬性 orderId 是變化的
_reply[orderId] = data.orderId
// 更新,只能這樣一波騷操作才能讓computed和watch監聽到。 state.reply = _reply

  具體原因其實跟第二章一樣,要保證其引用地址變了才行。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM