vuex

作者: 渚清与沙白 | 来源:发表于2023-10-01 13:59 被阅读0次

    概述

    • 组件之间共享数据的方式
      父向子传值:v-bind属性绑定
      子向父传值:v-on属性绑定
      兄弟组件之间共享数据:EventBus
      1. $on 接收数据的那个组件
      2. $emit 发送数据的那个组件
    • 全局共享数据
      vuex
    • vuex原理


      image.png

    vue2使用vuex 3版本
    vue3 使用vuex 4版本
    import vuex from 'vuex'
    Vue.use(vuex)

    // src/store/index.js
    import Vue from 'vue';
    import Vuex from 'vuex';
    
    Vue.use(Vuex);
    
    // 响应组件中的动作(异步)
    const actions = {};
    // 操作数据
    const mutations = {};
    // 存储数据
    const state = {};
    const getters = {};
    
    // 创建并导出store
    export default new Vuex.Store({
      state,
      getters,
      mutations,
      actions,
    });
    
    // main.js
    import Vue from 'vue'
    import App from './App.vue'
    import store from './store'
    Vue.config.productionTip = false
    
    new Vue({
      store,
      render: h => h(App),
    }).$mount('#app')
    

    State

    // 创建store数据源,提供唯一公共数据
    const store = new Vuex.Store({
      state:{
        count: 0
      }
    })
    

    组件访问State中数据的方式

    1. this.$store.state.count
      在template标签中可以省略this,{{ $store.state.count }}
    2. mapState 生成函数的作用 返回一个对象,key-value的value是一个函数
      image.png
    // 导入mapSate函数
    import { mapState } from 'vuex'
    // 将全局数据,映射为当前组件的计算属性
    computed:{
      ...mapState(['count']), // 数组写法 count就是computed的一个属性 
      ...mapState({count,'count'}), // 对象写法 key对应的count是computed对象的属性名;value对应的'count'是state对象的属性名,也是computed对象count属性的值(函数)
    }
    // 用法
    <h1> {{ count }} </h1>
    

    Mutation

    matation用于修改state中公共数据
    可以集中监控数据的变化

    // 创建store数据源,提供唯一公共数据
    const store = new Vuex.Store({
      state:{
        count: 0
      },
      mutations:{
        add(state) {
          // 变更状态
          state.aount++
        },
      //  触发mutation时 接收参数
      addNum(state,num) {
          // 变更状态
          state.aount += num;
        }
      }
    })
    

    触发mutation的第一种方式,使用commit

    methods: {
      handle(){
          // 不传参
          this.$state.commit('add');
      }
       handle2(){
          // 传参
          this.$state.commit('addNum',30);
       }
    }
    

    触发mutation的第二种方式mapMutations

    // 导入mapMutations函数
    import { mapMutations } from 'vuex'
    // 将mapMutations函数,映射为当前组件的methods方法
    methods: {
      ...mapMutations(['add','addNum']),
    handle(){
      // 调用方式
      this.add();
      this.addNum(2);
     }
    }
    

    Action

    Action 类似于 mutation,不同在于:
    Action 提交的是 mutation,而不是直接变更状态。
    Action 可以包含任意异步操作。
    处理异步任务
    触发actions异步任务时携带参数

    // 定义action
    const store = new Vuex.Store({
      state:{
        count: 0
      },
      mutations:{
        add(state) {
          // 变更状态
          state.aount++
        },
      //  触发mutation时 接收参数
      addNum(state,num) {
          // 变更状态
          state.aount += num;
        }
      },
      action: {
        addAsync(context, num) {
          setTimeout(()=>{
            context.commit('addNum',num);
          },1000)
       }
     }
    })
    

    触发action的第一种方式dispatch

    methods: {
      handle() {
        // 带参数
        this.$store.dispatch('addAsync',5);
      }
    }
    

    触发action的第二种方式mapActions

    // 导入mapActions函数
    import { mapActions } from 'vuex'
    // 将需要的actions函数,映射为当前组件的methods方法
    methods: {
      ...mapActions(['addAsync']),
     handle() {
        // 调用方式
        this.$state.addAsync(this.num); // @click="addAsync(num)"
     }
    }
    

    Getter

    用于对State中的数据进行加工处理形成新的数据,不会改变State中的数据
    State中数据发生变化,Getter的数据也会跟着变化

    // 定义getter
    const store = new Vuex.Store({
      state:{
        count: 0
      },
      mutations:{
        add(state) {
          // 变更状态
          state.aount++
        },
      //  触发mutation时 接收参数
      addNum(state,num) {
          // 变更状态
          state.aount += num;
        }
      },
      action: {
        addAsync(context, num) {
          setTimeout(()=>{
            context.commit('addNum',num);
          },1000)
       }
     },
    getters: {
      showNum: state => {
        return 'getter:'+state.count;
      }
    }
    })
    

    使用getters第一种方式getter
    this.$store.getter.showNum
    template中使用可以省略this关键字

    使用getters第二种方式mapGetters

    import { mapGetters } from 'vuex'
    computed: {
      ...mapGetters(['showNum'])
    },
    methods: {
      handle()  {
      this.showNum();
     }
    }
    
    mapState, mapGetters, mapMutations, mapActions的用法
    <template>
      <div>
        <p>当前值:{{sum}}</p>
        <p>当前学校:{{school}}</p>
        <p>当前科目:{{subject}}</p>
        <p>当前大数:{{bigSum}}</p>
        <p>当前学校:{{xuexiao}}</p>"
    
        <button @click="increment(n)">+</button>
        <button @click="decrement(n)">-</button>
        <button @click="incrementOdd(n)">+</button>
        <button @click="decrementOdd(n)">-</button>
      </div>
    </template>
    
    <script> 
    import {mapState, mapGetters, mapMutations, mapActions} from "vuex";
    export default {
      name: "Test",
      data() {
        return {
          n:0,
        };
      },
      computed: {
        // 借助mapState方法生成计算属性,从state中读取数据
        // 对象写法
       ...mapState({he:'sum',xuexiao:'school',xueke:'subject'}),
       // 数组写法
       ...mapState(["sum",'school','subject']),
    
       // 借助mapGetters方法生成计算属性,从getters中读取数据
       // 对象写法
       ...mapGetters({bigSum:'bigSum'}),
       // 数组写法
       ...mapGetters(['bigSum']),
      // 模块
       ...mapGetters('setting', ['firstMenu', 'subMenu', 'menuData']),
      },
      methods:{
        // mapMutations:借助mapMutations方法生成对应的方法,方法中会调用commit去联系mutations
        // 对象写法 
        ...mapMutations({increment:'JIA', decrement:'JIAN'}),
        // 数组写法
        ...mapMutations(["JIA","JIAN"]),
        // 模块account中的方法
        ...mapMutations("account", ["setUser", "setPermissions", "setRoles"]),
    
        // 借助mapActions方法生成对应的方法,方法中会调用dispatch去联系actions
        //  对象写法
       ...mapMutations({incrementOdd:'jiaOdd', decrementOdd:'jianOdd'}),
        //  数组写法
       ...mapActions(["jiaOdd","jianOdd"]),
      },
    };
    </script>
    

    模块化和命名空间modules namespaced

    1. 目的:更换维护,分类明确
    2. 优化store.js
    3. modules使用场景
      项目复杂管理大量的状态,此时可以使用modules方式进行拆分,每一个都具有state、getter、action、matation。
    4. 在模块中使用:namespaced: true, 命名空间,当前模块下的标识符可以和其它模块相同,用于解决不同模块的命名冲突问题
    5. store目录下,创建modules文件夹,该文件夹创建index.js及拆分的模块文件。store文件夹下的index.js再导入modules ,然后进行挂载。挂栽对象格式是{ modules: { account: {}, setting: {} } }
      image.png
    const countAbout = {
        namespaced:true,// 开启命名空间
        state: {num:1},
        mutations: { ... },
        actions: { ... },
        getters: {
            bigSum(state){
                return state.num * 10;
            }
        }
    }
    
    const personAbout = {
        namespaced:true,// 开启命名空间
        state: { ... },
        mutations: { ... },
        actions: { ... },
    }
    
    const store = new Vuex.Store({
        modules: {
            countAbout,
            personAbout
        }
    })
    
    1. 开启命名空间后,组件中读取state数据
    // 方式一 自己直接读取
    this.$store.state.personAbout.personList
    this.$store.state.countAbout.sum
    
    // 方式二 辅助mapState读取
    ...mapState('countAbout',['sum','shcool','subject'])
    
    
    1. 开启命名空间后,组件中读取getters数据
    // 方式一 自己直接读取
    this.$store.getters['personAbout/firstName']
    
    // 方式二 辅助mapGetters读取
    ...mapGetters('countAbout',['bigSum'])
    
    
    1. 开启命名空间后,组件中调用dispatch
    // 方式一 自己直调用dispatch
    this.$store.dispatch('personAbou/addPersonWang',personObj)
    
    // 方式二 辅助mapActions
    ...mapActions('countAbout',{incrementOdd:'jiaOdd'})
    
    
    1. 开启命名空间后,组件中调用commit
    // 方式一 自己直接调用commit
    this.$store.commit('personAbout/ADD_PERSON',personObj)
    
    // 方式二 辅助mapMutations
    ...mapMutations('countAbout',{increment:'JIA'})
    
    

    相关文章

      网友评论

          本文标题:vuex

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