Vuex進階

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>

 效果圖:

 

相關文章
相關標籤/搜索