1.插件vue
下面以一個對state進行持久化存儲的插件爲例進行介紹:vuex
代碼結構:瀏覽器
saveInLocal.jscookie
export default function (store) { if (localStorage.state) { store.replaceState(JSON.parse(localStorage.state)); } store.subscribe((mutation, state) => { //在HTML5中,新加入了一個localStorage特性,這個特性主要是用來做爲本地存儲來使用的,解決了cookie存儲空間不足的問題(cookie中每條cookie的存儲空間爲4k),localStorage中通常瀏覽器支持的是5M大小,這個在不一樣的瀏覽器中localStorage會有所不一樣。 localStorage.state = JSON.stringify(state); }); }
index.jsapp
import Vue from 'vue' import Vuex from 'vuex' import state from "./state" import getters from './getters' import mutations from "./mutations" import actions from "./actions" import user from './module/user' import saveInLocal from './plugin/saveInLocal'; Vue.use(Vuex) export default new Vuex.Store({ state, getters, mutations, actions, modules: { user }, plugins:[saveInLocal] })
store.vue:函數
<template> <div> <a-input :value="inputValue" @input="handlerInput"></a-input> <p>{{ inputValue }} -> lastLetter is {{ inputValueLastLetter }}</p> <p>appName: {{ appName }}, appNameWithVersion : {{ appNameWithVersion }}</p> <p>userName : {{ userName }}, firstLetter is : {{ firstLetter }}</p> <button @click="handleChangeAppName">修改appName和user.js中的userName</button> <p>動態給state增長appVersion: {{ appVersion }}</p> <button @click="handleActionChangeAppName">經過Action修改appName</button> <button @click="registerModule">動態註冊模塊</button> <p v-for="(li, index) in todoList" :key="index">{{ li }}</p> </div> </template> <script> import AInput from "_c/AInput.vue"; import AShow from "_c/AShow.vue"; //變量的解構賦值 import { mapState, mapGetters, mapMutations, mapActions } from "vuex"; import { stat } from "fs"; export default { name: "store", data() { return { inputValue: "" }; }, components: { AInput: AInput, AShow: AShow }, computed: { //ES6展開操做符 mapState展開會造成一個對象 使用對象展開運算符將此對象混入到外部對象中 ...mapState({ appName: state => state.appName, appVersion: state => state.appVersion, userName: state => state.user.userName, todoList: state => (state.user.todo ? state.user.todo.todoList : []) }), // 使用對象展開運算符將 getter 混入 computed 對象中 // ...mapGetters(["appNameWithVersion"]), appNameWithVersion() { //經過屬性訪問getters,Getter 會暴露爲 store.getters 對象,能夠以屬性的形式訪問這些值: return this.$store.getters.appNameWithVersion; }, ...mapGetters(["firstLetter"]), inputValueLastLetter() { return this.inputValue.substr(-1, 1); } }, methods: { handlerInput(val) { this.inputValue = val; }, // ...mapMutations([ "SET_USER_NAME", //將 `this.SET_USER_NAME()` 映射爲 `this.$store.commit('SET_USER_NAME')` "SET_APP_NAME" //將 `this.SET_APP_NAME()` 映射爲 `this.$store.commit('SET_APP_NAME')` ]), ...mapActions([ "updateAppName" //將 `this.updateAppName()` 映射爲 `this.$store.dispatch('updateAppName')` ]), handleChangeAppName() { this.SET_APP_NAME({ appName: "newAppName" }); this.SET_USER_NAME({ userName: "shuyujie" }); this.$store.commit("SET_APP_VERSION"); }, handleActionChangeAppName() { //第一種調用Action的方法 //this.$store.dispatch('updateAppName') //第二種調用Action的方法 this.updateAppName(); }, registerModule() { this.$store.registerModule(["user", "todo"], { state: { todoList: ["學習mutations", "學習actions"] } }); } } }; </script>
點擊名稱爲:「修改appName和user.js中的userName」的按鈕:工具
效果圖:學習
2.嚴格模式this
在嚴格模式下,不管什麼時候發生了狀態變動且不是由 mutation 函數引發的,將會拋出錯誤。這能保證全部的狀態變動都能被調試工具跟蹤到。spa
index.js代碼:
import Vue from 'vue' import Vuex from 'vuex' import state from "./state" import getters from './getters' import mutations from "./mutations" import actions from "./actions" import user from './module/user' import saveInLocal from './plugin/saveInLocal'; Vue.use(Vuex) export default new Vuex.Store({ strict: process.env.NODE_ENV === 'development',//不要在發佈環境下啓用嚴格模式! state, getters, mutations, actions, modules: { user }, plugins:[saveInLocal] })
3.Vuex+雙向數據綁定
當在嚴格模式中使用 Vuex 時,在屬於 Vuex 的 state 上使用 v-model
會比較棘手,由於state只容許被mutation修改。
解決辦法:使用帶有 setter 的雙向綁定計算屬性
state.js:
const state = { appName: 'admin', stateValue: 'I am stateValue' } export default state
mutations.js:
import vue from 'vue' const mutations = { SET_APP_NAME(state, params) { //若params是對象格式 state.appName = params.appName; //若params是字符串格式 //state.appName = params; }, SET_APP_VERSION(state) { vue.set(state, 'appVersion', 'v100.0') //state.appVersion = 'v2.0' }, SET_STATE_VALUE (state, value) { state.stateValue = value } } export default mutations;
store.vue:
<template> <div> <a-input v-model="stateValue"/> <p>{{ stateValue }}</p> <p>appName: {{ appName }}, appNameWithVersion : {{ appNameWithVersion }}</p> <p>userName : {{ userName }}, firstLetter is : {{ firstLetter }}</p> <button @click="handleChangeAppName">修改appName和user.js中的userName</button> <p>動態給state增長appVersion: {{ appVersion }}</p> <button @click="handleActionChangeAppName">經過Action修改appName</button> <button @click="registerModule">動態註冊模塊</button> <p v-for="(li, index) in todoList" :key="index">{{ li }}</p> </div> </template> <script> import AInput from "_c/AInput.vue"; import AShow from "_c/AShow.vue"; //變量的解構賦值 import { mapState, mapGetters, mapMutations, mapActions } from "vuex"; import { stat } from "fs"; export default { name: "store", data() { return { inputValue: "" }; }, components: { AInput: AInput, AShow: AShow }, computed: { //ES6展開操做符 mapState展開會造成一個對象 使用對象展開運算符將此對象混入到外部對象中 ...mapState({ appName: state => state.appName, appVersion: state => state.appVersion, userName: state => state.user.userName, todoList: state => (state.user.todo ? state.user.todo.todoList : []) }), // 使用對象展開運算符將 getter 混入 computed 對象中 // ...mapGetters(["appNameWithVersion"]), appNameWithVersion() { //經過屬性訪問getters,Getter 會暴露爲 store.getters 對象,能夠以屬性的形式訪問這些值: return this.$store.getters.appNameWithVersion; }, stateValue: { get () { return this.$store.state.stateValue }, set (val) { this.SET_STATE_VALUE(val) } }, ...mapGetters(["firstLetter"]), inputValueLastLetter() { return this.inputValue.substr(-1, 1); } }, methods: { handlerInput(val) { this.inputValue = val; }, // ...mapMutations([ "SET_USER_NAME", //將 `this.SET_USER_NAME()` 映射爲 `this.$store.commit('SET_USER_NAME')` "SET_APP_NAME", //將 `this.SET_APP_NAME()` 映射爲 `this.$store.commit('SET_APP_NAME')` 'SET_STATE_VALUE' ]), ...mapActions([ "updateAppName" //將 `this.updateAppName()` 映射爲 `this.$store.dispatch('updateAppName')` ]), handleChangeAppName() { this.SET_APP_NAME({ appName: "newAppName" }); this.SET_USER_NAME({ userName: "shuyujie" }); this.$store.commit("SET_APP_VERSION"); }, handleActionChangeAppName() { //第一種調用Action的方法 //this.$store.dispatch('updateAppName') //第二種調用Action的方法 this.updateAppName(); }, registerModule() { this.$store.registerModule(["user", "todo"], { state: { todoList: ["學習mutations", "學習actions"] } }); } } }; </script>
AInput.js:
<template> <div> <input @input="handleInput" :value="value"/> </div> </template> <script> export default { name:'AInput', props:{ value:{ type:[String,Number], default:'' } }, methods:{ handleInput(event){ const value=event.target.value; this.$emit('input',value); } } } </script>
效果圖: