在樓主的一個自動化測試項目中,由於UI用例運行時間較長,要允許別人暫時去別的頁面做別的事情,然後返回時可以看到運行結果。要實現這個功能,就需要保存當前頁面數據,以便路由回來時還能獲取上次的數據。因此必須將原來單文件組件中的data數據移至vuex中的store裏面去保存。
在做完更改後,發現部分數據丟失,並沒有恢復。通過vue-devtool查看state數據,發現出現了兩個targetKeys屬性,後來對比發現,原來其中一個叫targetKyes!這個屬性是哪裏來的?我的store模塊定義如下:
/**
* 運行UI用例管理
* */
import * as mutations from './mutations';
import * as actions from './actions';
const runUiCases = {
state: { // state數據
selectGroup:[],//下拉框選擇的用例組
targetKeys:[],// 待跑用例id列表
isRunning: false,//保存用例是否在運行狀態,用於長時間運行時,可以自由跳轉到別的頁面先做別的事,然後返回時判斷用例是否允許完畢
groupList: [], //功能點列表
casesList: [], // 用例列表
reporter: {
totalTime: 0,
count: 0,
passCount: 0,
allPass: true,
messageList: []
} //結果
},
mutations,
actions
};
export default runUiCases;
很明顯,只有一個targetKeys屬性,並且按照一般的經驗,屬性一般都是要提前定義好的,不允許中途加屬性。後來想到能操縱state的只有mutation,翻到mutation一看,果然:
// 更新待跑用例keys
export const SET_TARGET_KEYS = (state, payload) => {// mutation第一個參數是state對象,第二個參數是傳進來的額外參數
state.targetKyes = payload;
};
這裏由於拼寫錯誤,爲state添加了一個新的屬性!數據都保存到新屬性裏面去了,因此就出現了部分數據恢復不了的現象。
坑!怎麼能如此輕易的就可以改變state的數據?
特地去查了下官網,官網的描述如下:
Mutation 需遵守 Vue 的響應規則
既然 Vuex 的 store 中的狀態是響應式的,那麼當我們變更狀態時,監視狀態的 Vue 組件也會自動更新。這也意味着 Vuex 中的 mutation 也需要與使用 Vue 一樣遵守一些注意事項:
-
最好提前在你的 store 中初始化好所有所需屬性。
-
當需要在對象上添加新屬性時,你應該
-
使用
Vue.set(obj, 'newProp', 123)
, 或者 -
以新對象替換老對象。例如,利用 stage-3 的對象展開運算符我們可以這樣寫:
state.obj = { ...state.obj, newProp: 123 }
說說我的看法。第1點很好理解,這樣做state有哪些屬性可以一目瞭然。可是!第2點,需要添加新屬性的時候使用Vue.set()還能說得過去,你直接新對象替換老對象也行?Excuse Me?這不是在埋坑嗎?到時候操作屬性的時候,A發現state沒有這個屬性,通過新對象替換老對象,添加了屬性。但其實這個屬性B已經用同樣的方式添加過了,而且類型不是A想要的那種。又或者,A想查看state有沒有某個屬性,他看了一眼state,沒有,卻不敢直接說沒有,因爲可能別的地方加了。
因此,上述規則的第2點,我認爲不可取。後面出現新屬性,完全可以直接添加到state中去即可。如果你太懶,鐵了心要用第2種,我覺得使用Vue.set()也要比直接替換好很多!而且最好新屬性通過常量定義好,這樣查詢state有哪些屬性的時候,就可以從state和常量兩個地方查就夠了。但與其這麼麻煩,爲什麼不直接添加呢?
回到我遇到的這個坑,如果mutation有限制,不能直接增刪屬性,必須通過類似mutation本身這樣機制,那這個問題就可以避免或者說提前暴露出來。