vuex

作者: WebsnowDrop | 来源:发表于2024-08-06 18:12 被阅读0次

    什么是Vuex

    Vuex 是一个专为 Vue.js 应用程序开发的状态管理库。

    安装和引入vuex

    • 安装
    yarn add vuex
    
    • 引入
      一般将项目应用级的状态都放到store中统一管理,项目新建一个store文件夹,这个里面存放所需的状态
    //store/index.js
    import Vue from 'vue'
    import Vuex from 'vuex'
    Vue.use(Vuex);
    const store = new Vuex.Store({
        state:{
            count:0
        },
        getters:{},
        mutations:{},
        actions:{}
    })
    export default store
    

    定义好store后再main.js中引用

    //main.js
    import Vue from "vue";
    import App from "./App.vue";
    + import store from "./store";
    Vue.config.productionTip = false;
    new Vue({
      render: (h) => h(App),
    +  store,
    }).$mount("#app");
    
    

    核心概念

    • State

    State中存储公共数据。例如组件A和组件B共同用到的数据count,在组件A中修改count的值,组件B中count会随之更改

    • 如何使用?两种方式:
    1. 在模版中使用$store.state.count
    //store中定义count
    const store = new Vuex.Store({
      state: {
        count: 1,
      },
      getters: {
      },
      mutations: {},
      actions: {},
    });
    //模版中使用$store.state.count
    <template>
      <div id="app">
        <img alt="Vue logo" src="./assets/logo.png" />
        <div>{{ $store.state.count }}</div>
      </div>
    </template>
    
    1. 在计算属性computed中使用
    • 在compute中定义
    <template>
      <div id="app">
        <img alt="Vue logo" src="./assets/logo.png" />
        <div>{{ count }}</div>
      </div>
    </template>
    <script>
    export default {
      name: "App",
      computed: {
        count(){
            return this.$store.state.count
        }
      },
    };
    </script>
    
    • 借助mapState辅助函数
    <template>
      <div id="app">
        <img alt="Vue logo" src="./assets/logo.png" />
        <div>{{ count }}</div>
      </div>
    </template>
    
    <script>
    import { mapState } from "vuex";
    export default {
      name: "App",
      computed: {
        ...mapState(["count"]),
      },
    };
    </script>
    
    • Getters

    存放从State中派生的一些状态数据,相当于State的计算属性,getter 的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。

    • 如何使用?两种方式:
    1. 在模版中使用$store.getters.newCount
    //store中定义
    const store = new Vuex.Store({
      state: {
        count: 1,
      },
      getters: {
        newCount: (state) => {
          return state.count * 2;
        },
      },
      mutations: {},
      actions: {},
    });
    //模版中使用
    <template>
      <div id="app">
        <img alt="Vue logo" src="./assets/logo.png" />
        <div>{{ $store.state.newCount}}</div>
        <div>{{ $store.getters.newCount}}</div>
      </div>
    </template>
    
    1. 使用mapGetters辅助函数
    <template>
      <div id="app">
        <img alt="Vue logo" src="./assets/logo.png" />
        <!-- <div>{{ $store.state.count }}</div> -->
        <div>{{ count }}</div>
        <div>{{ newCount }}</div>
      </div>
    </template>
    
    <script>
    import { mapState,mapGetters } from "vuex";
    export default {
      name: "App",
      computed: {
        ...mapState(["count"]),
        ...mapGetters(["newCount"]),
        
      },
    };
    </script>
    
    • Mutations

    修改State的数据唯一方法就是commit一个mution中的方法,修改state时要调用store.commit(state,payload)提交一个payload来更改

    • 如何使用?两种方式:
    1. 调用store.commit
    //store中
    const store = new Vuex.Store({
      state: {
        count: 1,
      },
      getters: {
        newCount: (state) => state.count * 2,
      },
      mutations: {
        addCount(state, payload) {
          setTimeout(() => {
            payload;
            state.count++;
          },1000);
        },
      },
      actions: {},
    });
    //模版中
    <template>
      <div id="app">
        <img alt="Vue logo" src="./assets/logo.png" />
        <div>{{ count }}</div>
        <div>
          <button @click="handleClick">提交</button>
        </div>
        <div>{{ newCount }}</div>
      </div>
    </template>
    
    <script>
    import { mapState, mapGetters,} from "vuex";
    export default {
      name: "App",
      methods: {
        handleClick() {
          this.$store.commit({
            type: "addCount",
            num: parseInt(Math.random() * 10),
          });
        },
      },
      computed: {
        ...mapState(["count"]),
        ...mapGetters(["newCount"]),
      },
    };
    </script>
    
    1. 使用mapMutations辅助函数
    <template>
      <div id="app">
        <img alt="Vue logo" src="./assets/logo.png" />
        <div>{{ count }}</div>
        <div>
          <button @click="addCount">提交</button>
        </div>
        <div>{{ newCount }}</div>
      </div>
    </template>
    
    <script>
    import { mapState, mapGetters, mapMutations } from "vuex";
    export default {
      name: "App",
      methods: {
        ...mapMutations(["addCount"]),
        handleClick() {
            this.addCount(Math.random() * 10)
        },
      },
      computed: {
        ...mapState(["count"]),
        ...mapGetters(["newCount"]),
      },
    };
    </script>
    

    注意:mutation必须是同步函数

    • Actions

    Actions和Mutations相似,不同的是:

    1. Actions提交的是一个mutation,而不是直接改变state
    2. Actions可以提交异步操作
    • 如何使用?两种方式:
    1. 调用store.dispatch
    //store中
    const store = new Vuex.Store({
      state: {
        count: 1,
      },
      getters: {
        newCount: (state) => state.count * 2,
      },
      mutations: {
        addCount(state, payload) {
          state.count += payload.num;
        },
      },
      actions: {
        addCountAsync(context) {
          setTimeout(() => {
            const { commit } = context;
            commit("addCount", { num: 1 });
          });
        },
      },
    });
    //template中
    <template>
      <div id="app">
        <img alt="Vue logo" src="./assets/logo.png" />
        <div>{{ count }}</div>
        <div>
          <button @click="action">action</button>
        </div>
        <div>{{ newCount }}</div>
      </div>
    </template>
    <script>
    import { mapState, mapGetters, mapMutations } from "vuex";
    export default {
      name: "App",
      methods: {
        action() {
          this.$store.dispatch("addCountAsync", { num: 1 });
        },
      },
      computed: {
        ...mapState(["count"]),
        ...mapGetters(["newCount"]),
      },
    };
    </script>
    
    1. 使用mapActions辅助函数
    <template>
      <div id="app">
        <img alt="Vue logo" src="./assets/logo.png" />
        <div>{{ count }}</div>
        <div>
          <button @click="action">action</button>
        </div>
        <div>{{ newCount }}</div>
      </div>
    </template>
    
    <script>
    import { mapState, mapGetters, mapMutations, mapActions } from "vuex";
    export default {
      name: "App",
      methods: {
        ...mapMutations(["addCount"]),
        ...mapActions(["addCountSync"]),
        handleClick() {
          // this.addCount({ num: parseInt(Math.random() * 10) });
          this.$store.commit({
            type: "addCount",
            num: 2,
          });
        },
        action() {
          // this.$store.dispatch("addCountAsync", { num: 1 });
          this.addCountSync({ num: 1 });
        },
      },
      computed: {
        ...mapState(["count"]),
        ...mapGetters(["newCount"]),
      },
    };
    </script>
    
    • Modules

    当所有数据都放入store中,当应用变得非常复杂时,store 对象就有可能变得相当臃肿。Modules的作用就是将store划分为不同的模块,每个Modules都包含state,getters,mutations,actions。这样做方便代码维护,结构更清晰

    const moduleA = {
      state: () => ({ ... }),
      mutations: { ... },
      actions: { ... },
      getters: { ... }
    }
    
    const moduleB = {
      state: () => ({ ... }),
      mutations: { ... },
      actions: { ... }
    }
    
    const store = new Vuex.Store({
      modules: {
        a: moduleA,
        b: moduleB
      }
    })
    
    store.state.a // -> moduleA 的状态
    store.state.b // -> moduleB 的状态
    

    相关文章

      网友评论

          本文标题:vuex

          本文链接:https://www.haomeiwen.com/subject/txnfkjtx.html