1. 程式人生 > >Vuex 嚴格模式下 form表單處理 比官網更好的辦法

Vuex 嚴格模式下 form表單處理 比官網更好的辦法

# Vuex form表單處理 比官網更好的辦法 > 問題, 當使用vuex的state作為表單的v-model元素, 雖然簡單粗暴, 但這種修改沒有經過mutation方法. 在嚴格模式下會丟擲錯誤 [TOC] ## 1. 錯誤提示 錯誤程式碼如下 ![](http://cdn.xiaxiang.tech/image/blogs/vue/vuex/表單處理1.png) [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中相關程式碼 ```js 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變數
元件中相關程式碼 ```js // 獲取vuex中user ...mapGetters('module1', [ 'user', ]), // 改變vuex中user狀態 ...mapMutations('module1', [ 'changeObject', ]), ```
## 3. 官網建議方法 - 給 `` 中繫結 value,然後偵聽 `input` 或者 `change` 事件,在事件回撥中呼叫一個方法 - 另一個方法是使用帶有 setter 的雙向繫結計算屬性 ```js // ... computed: { message: { get () { return this.$store.state.obj.message }, set (value) { this.$store.commit('updateMessage', value) } } } ``` **這兩種方法都有一種很大的缺陷, 必須定義每個輸入元素的變數, 比如, 現在有個表單, 裡面有20個元素, 那麼此時就要寫20個方法來響應輸入框的變化, 作為工匠人, 不得不採取更好的辦法**
--- ## 4. 解決方案 個人在網上找了一些解決方案, 有用proxy代理, 有封裝一些方法的, 這些在我看來, 都挺勉強的 經過一系列嘗試, 我改良了官網描述的第二種方法, 將**表單元素與vuex雙向繫結, 並且經過了mutation, 嚴格模式下不報錯** 核心程式碼如下 定義表單物件 ```js // 定義在computed下 object: { set(val){ // console.log(val); this.changeObject(val); }, //這裡需要注意, 獲取的是user資訊, 並非物件, 採用擴充套件運算子處理 get(){ return {...this.user} } } ``` 獲取表單變化程式碼 ```js // ... methods中方法 inputChange(){ this.object = {...this.object} }, ```
--- ## 5. 整體解釋 1. vuex定義username和password 2. object 通過 get 獲取到username和password進行初始化 3. 表單輸入觸發inputChange方法改變 object 物件, 觸發object物件的 set 方法 4. object的 set 方法改變了 vuex中的值 5. vuex 值發生改變, 從而觸發 object 的 get 方法 6. object值發生改變, 從而形成一個迴圈鏈 ```mermaid graph TD; A(vuex定義變數) --> B(初始化表單object) B --> C(表單輸入觸發inputChange方法) C --> D(inputChange觸發object的set方法) D --> E(object的set方法改變vuex中的狀態變數) E --> F(vuex狀態變化觸發object的get方法) ``` 1. 初始狀態 ![](http://cdn.xiaxiang.tech/image/blogs/vue/vuex/初始狀態.png) 2. 改變username後的狀態 ![image-20201125204440609](http://cdn.xiaxiang.tech/C:/Users/xx/AppData/Roaming/Typora/typora-user-images/image-20201125204440609.png) 3. 改變password後的狀態 ![](http://cdn.xiaxiang.tech/image/blogs/vue/vuex/改變password後狀