Vuex form表單處理, 比官網更好的辦法
Vuex form表單處理, 比官網更好的辦法
問題, 當使用vuex的state作為表單的v-model元素, 雖然簡單粗暴, 但這種修改沒有經過mutation方法. 在嚴格模式下會拋出錯誤
1. 錯誤提示
錯誤程式碼如下
[Vue warn]: Error in callback for watcher “function () { return this._data.$$state }”: “Error: [vuex] do not mutate vuex store state outside mutation handlers.”
2. 相關場景
vuex中相關程式碼
const state = ()=>({
user: {
username: '123',
password: '123',
}
});
const getters = {
userName: state=>state.userName,
user: state=>state.user,
};
const mutations = {
changeObject(state, payload){
// es6語法
state.user = {...state.user, ...payload};
},
};
其中定義了user變數
組件中相關程式碼
// 獲取vuex中user
...mapGetters('module1', [
'user',
]),
// 改變vuex中user狀態
...mapMutations('module1', [
'changeObject',
]),
3. 官網建議方法
- 給
<input>
中綁定 value,然後偵聽input
或者change
事件,在事件回調中調用一個方法 - 另一個方法是使用帶有 setter 的雙向綁定計算屬性
// ...
computed: {
message: {
get () {
return this.$store.state.obj.message
},
set (value) {
this.$store.commit('updateMessage', value)
}
}
}
這兩種方法都有一種很大的缺陷, 必須定義每個輸入元素的變數, 比如, 現在有個表單, 裡面有20個元素, 那麼此時就要寫20個方法來響應輸入框的變化, 作為工匠人, 不得不採取更好的辦法
4. 解決方案
個人在網上找了一些解決方案, 有用proxy代理, 有封裝一些方法的, 這些在我看來, 都挺勉強的
經過一系列嘗試, 我改良了官網描述的第二種方法, 將表單元素與vuex雙向綁定, 並且經過了mutation, 嚴格模式下不報錯
核心程式碼如下
定義表單對象
// 定義在computed下
object: {
set(val){
// console.log(val);
this.changeObject(val);
},
//這裡需要注意, 獲取的是user資訊, 並非對象, 採用擴展運算符處理
get(){
return {...this.user}
}
}
獲取表單變化程式碼
<form :model="object" @input="inputChange">
<input type="text" v-model="object.username">
<input type="text" v-model="object.password">
</form>
// ... methods中方法
inputChange(){
this.object = {...this.object}
},
5. 整體解釋
- vuex定義username和password
- object 通過 get 獲取到username和password進行初始化
- 表單輸入觸發inputChange方法改變 object 對象, 觸發object對象的 set 方法
- object的 set 方法改變了 vuex中的值
- vuex 值發生改變, 從而觸發 object 的 get 方法
- object值發生改變, 從而形成一個循環鏈
A(vuex定義變數) –> B(初始化表單object)
B –> C(表單輸入觸發inputChange方法)
C –> D(inputChange觸發object的set方法)
D –> E(object的set方法改變vuex中的狀態變數)
E –> F(vuex狀態變化觸發object的get方法)
- 初始狀態
- 改變username後的狀態
- 改變password後的狀態