• Vuex进阶


    1.插件

    下面以一个对state进行持久化存储的插件为例进行介绍:

     代码结构:

    saveInLocal.js

    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.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({
      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.严格模式

    在严格模式下,无论何时发生了状态变更且不是由 mutation 函数引起的,将会抛出错误。这能保证所有的状态变更都能被调试工具跟踪到。

    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>

     效果图:

     

  • 相关阅读:
    Facebook发布神经蛋分离法,可从嘈杂环境中提取音视频
    前线观察 | AWS re:Invent 2018见闻实录
    SSO
    8-5 Navicat工具与pymysql模块
    saltstack
    nginx 集群介绍
    Docker 持久化存储
    Docker 多机网络
    《深入理解JAVA虚拟机》笔记1
    jquery 学习日记之选择器
  • 原文地址:https://www.cnblogs.com/qicao/p/10800489.html
Copyright © 2020-2023  润新知