跳至主要內容

Vuex

望间代码VueVuex大约 3 分钟

Vuex

状态管理工具

Vuex
Vuex
import Vue from "vue";
import Vuex from "vuex";

Vue.use(Vuex);

export default new Vuex.Store({
  state: {},
  getters: {},
  mutations: {},
  actions: {},
  modules: {},
});

State

用来存储公共状态

state: {
  count: 0;
}

组件直接调用 state 中的数据

this.$store.state.count;

也可以再计算属性中使用

computed: {
    count() {
        return this.$store.state.count
    }
}

辅助函数 - mapState

将 state 中的数据映射到组件的计算属性中

import { mapState } form 'vuex'

export default {
    computed: {
        /* 拓展运算符 */
        ...mapState(['count'])
    }
}

mapState()返回值为对象


import { mapState } form 'vuex'

export default {
    computed: {
        ...mapState({myCount: 'count'})
    }
}

mapState()除了接收数组以外,还可以接收对象

用于给 state 中的数据取别名

Getters

相当于 store 的计算属性,只有依赖值发生改变就会重新计算

getters: {
  num: (state) => parseInt(state.count);
}

组件中直接使用 getters 中的数据

this.$store.getters.num;

也可以再计算属性中使用

computed: {
    num() {
        return this.$store.getters.num
    }
}

辅助函数 - mapGetters

import { mapGetters } form 'vuex'

export default {
    computed: {
        /* 拓展运算符 */
        ...mapGetters(['num'])
    }
}

Mutations

操作 State 中的数据(只能执行同步代码),目的是形成数据快照

数据快照:一次 mutations 执行,立即生成一种视图状态

state: {
  count: 0
},
mutations: {
    addCount(state, payload) {
        state.count += payload
    }
}

参数:

  • state:就是 Vuex 中的 state 对象
  • payload:载荷(可以是任何形式的数据)

组件直接调用 mutations 方法

methods: {
    addCount() {
        this.$store.commit('addCount', 1)
    }
}

参数:

  • 第一个参数:就是 mutations 方法名
  • 第二个参数:就是载荷

使用对象风格传参

methods: {
    addCount() {
        this.$store.commit({
            type: 'addCount',
            num: 1
        })
    }
}
state: {
  count: 0
},
mutations: {
    addCount(state, payload) {
        state.count += payload.num
    }
}

使用对象风格传参,就是将整个对象作为参数传给 payload

辅助函数 - mapMutations

将 mutations 中的方法映射在组件的 methods 中

import { mapMutations } form 'vuex'

export default {
    methods: {
        ...mapMutations(['addCount'])
    }
}

使用辅助函数调用 mutations 方法时,如果需要传入载荷,则需要在组件中调用方法时传入参数

<button @click="addCount(1)"></button>

import { mapMutations } form 'vuex'

export default {
    methods: {
        ...mapMutations({add: 'addCount'})
    }
}

mapMutations 函数同样支持对象格式传参,给方法取别名

Actions

执行异步操作

actions 提交的是 mutations 方法,而不是改变数据

actions: {
    addCount(context, params) {
        context.commit('addCount', payload)
    }
}

参数:

  • context:与 store 相同属性和方法的对象
  • payload:载荷

组件直接调用 actions 方法

this.$store.dispatch("addCount", 1);

使用对象风格传参

methods: {
    addCount() {
        this.$store.dispatch({
            type: 'addCount',
            num: 1
        })
    }
}
state: {
  count: 0
},
actions: {
    addCount(context, payload) {
        context.commit('addCount', payload.num)
    }
}

使用对象风格传参,就是将整个对象作为参数传给 payload

辅助函数 - mapActions

import { mapActions } form 'vuex'

export default {
    methods: {
        ...mapActions(['addCount'])
    }
}

传参方式与 mapMutations 函数相同


import { mapActions } form 'vuex'

export default {
    methods: {
        ...mapActions({add: 'addCount'})
    }
}

mapActions 函数同样支持对象格式传参,给方法取别名

模块化

store
├── index.js # 我们组装模块并导出 store 的地方
├── actions.js # 根级别的 action
├── mutations.js # 根级别的 mutation
└── modules
├── user.js # 用户模块
└── setting.js # 设置模块

modules

将 store 拆除多个模块,每个模块都有自己的 state、mutation、action、getter

import Vue from "vue";
import Vuex from "vuex";

Vue.use(Vuex);

const user = {
  state: {},
  getters: {},
  mutations: {},
  actions: {},
};

export default new Vuex.Store({
  modules: {
    user,
    setting: {
      state: {},
      getters: {},
      mutations: {},
      actions: {},
    },
  },
});

./store/modules/moduleA.js

const user = {
  state: {},
  getters: {},
  mutations: {},
  actions: {},
};

export default user;

./store/index.js

import Vue from "vue";
import Vuex from "vuex";
import user from "./modules/user";

Vue.use(Vuex);

export default new Vuex.Store({
  modules: {
    user,
  },
});

可以将每个 module 拆成一个文件,单独编写,提高独立性

最后由 ./store/index.js 统一导入、抛出

命名空间

namespaced

默认情况下,模块下的 state、getters、actions、mutations 都是全局命名空间

也就是在全局都可以直接调用


如果需要实现高封闭性,这需要设置命名空间namespaced: true

user: {
    namespaced: true,
    state: {
    },
    getters: {
    },
    mutations: {
    },
    actions: {
    }
}

这样外部就不能直接调用 user 模块内部的 mutations、actions、getters

调用带命名空间的模块

  1. 带模块名调用
this.$store.commit(["user/changeInfo"]);
  1. 辅助函数带模块名调用
import { mapMutations } from 'vuex'
export default {
  methods: {
    ...mapMutations(['user/changeInfo'])

    change() {
        this['user/changeInfo']()
    }
  }
}
  1. createNamespacedHelpers
import { createNamespacedHelpers } from "vuex";

const { mapMutations } = createNamespacedHelpers("user");

export default {
  methods: {
    ...mapMutations(["changeInfo"]),
  },
};
上次编辑于:
贡献者: ViewRoom