1. 直接修改与commit提交mutation修改state的差异
- 共同点: 能够修改state里的变量,并且是响应式的
- 不同点:
若将vue创建 store 的时候传入
strict: true, 开启严格模式,那么任何修改state的操作,只要不经过 mutation的函数都会报错
一般来说,我们都是通过mutation来修改state的
使用commit提交到mutation修改state的优点:
- 代码结构更清晰
- 可以复用代码,提高开发效率
2. Vuex中状态是对象时要注意什么
因为对象是引用类型,复制后改变属性还是会影响原始数据,这样会改变state里面的状态,是不允许,所以先用深度克隆复制对象,再修改。
3. 组件中批量使用Vuex的state状态
使用mapState辅助函数, 利用对象展开运算符将state混入computed对象中
import {mapState} from 'vuex'
export default{
computed:{
...mapState(['a','b'])
}
}
4. 怎么从state派生一些状态出来让多个组件使用它
- 使用getter属性,相当Vue中的计算属性computed,只有原状态改变派生状态才会改变。
- getter接收两个参数,第一个是
state,第二个是getters(可以用来访问其他getter)。
const store = new Vuex.Store({
state: {
a: 10,
b: 10,
c: 0.7,
},
getters: {
total: state => {
return state.a * state.b
},
getTotal: (state, getters) => { // 这里的getters当前Vuex中的getters
return state.c * getters.total
}
},
});
然后在组件中可以用计算属性computed通过this.$store.getters.total这样来访问这些派生转态。
computed: {
total() {
return this.$store.getters.total
},
getTotal() {
return this.$store.getters.getTotal
}
}
5. 用getter来过滤state
通过让getter返回一个函数,来实现给getter传参。然后通过参数来进行判断从而获取state中满足要求的状态。
const store = new Vuex.Store({
state: {
todos: [
{ id: 1, text: '...', done: true },
{ id: 2, text: '...', done: false }
]
},
getters: {
getTodoById: (state) => (id) =>{
return state.todos.find(todo => todo.id === id)
}
},
});
然后在组件中可以用计算属性computed通过this.$store.getters.getTodoById(2)这样来访问这些派生转态。
computed: {
getTodoById() {
return this.$store.getters.getTodoById
},
}
mounted(){
console.log(this.getTodoById(2)) // { id: 2, text: '...', done: false }
}
6.组件中批量给getter属性取别名
使用mapGetters辅助函数, 利用对象展开运算符将getter混入computed 对象中
import {mapGetters} from 'vuex'
export default{
computed:{
...mapGetters({
myTotal:'total', //给getter中的total取别名myTotal
myDiscountTotal:'discountTotal',
})
}
}
7. 怎么改变state的状态。
参考答案
首先要在mutations中注册一个mutation
const store = new Vuex.Store({
state: {
number: 10,
},
mutations: {
SET_NUMBER(state,data){ //data是外界传过来的
state.number=data;
}
},
});
在组件中使用this.$store.commit提交mutation,改变number
this.$store.commit('SET_NUMBER',10)
8. action和mutation的区别
- action 提交的是 mutation,而
不是直接变更状态。mutation可以直接变更状态。 action可以包含任意异步操作。mutation只能是同步操作。- 提交方式不同,action 是用this.store.
commit('SET_NUMBER',10)来提交。 - 接收参数不同,mutation第一个参数是
state,而action第一个参数是context,其包含了
{
state, // 等同于 `store.state`,若在模块中则为局部状态
rootState, // 等同于 `store.state`,只存在于模块中
commit, // 等同于 `store.commit`
dispatch, // 等同于 `store.dispatch`
getters, // 等同于 `store.getters`
rootGetters // 等同于 `store.getters`,只存在于模块中
}
9. 如何知道异步的action何时结束
在action函数中返回Promise,然后再提交时候用then处理
actions:{
SETA({commit},data){
return new Promise((resolve,reject) =>{
setTimeout(() =>{
commit('SET_NUMBER',10);
resolve();
},2000)
})
}
}
this.$store.dispatch('SETA').then(() => {
// ...action SETA 执行完后就会执行这里
})
10. Vuex中有两个action,分别是actionA和actionB,其内都是异步操作,在actionB里面要提交actionA,需在actionA处理结束再执行actionB?
利用ES6的async和await来实现。
actions:{
async actionA({commit}){
//...
},
async actionB({dispatch}){
await dispatch ('actionA')//等待actionA完成
// ...
}
}
11. Vuex模块的简单使用
为什么要用模块化呢?
因为使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象就有可能变得相当臃肿。
所以将 store 分割成模块(module)。每个模块拥有自己的 state、mutations、actions、getters,甚至是嵌套子模块,从上至下进行同样方式的分割。
在module文件新建moduleA.js和moduleB.js文件。在文件中写入:
const state={
//...
}
const getters={
//...
}
const mutations={
//...
}
const actions={
//...
}
export default{
state,
getters,
mutations,
actions
}
然后再index.js引入模块
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
import moduleA from './module/moduleA'
import moduleB from './module/moduleB'
const store = new Vuex.Store({
modules:{
moduleA,
moduleB
}
})
export default store
12. 模块中getter和mutation接收的第一个参数state,是全局的还是模块的?
第一个参数state是模块的state,也就是局部的state。
13. 在模块中怎么访问全局的state和getter
- 在
getter中可以通过第三个参数rootState访问到全局的state,可以通过第四个参数rootGetters访问到全局的getter。 - 在
mutation中不可以访问全局的satat和getter,只能访问到局部的state。 - 在
action中第一个参数context中的context.rootState访问到全局的state,context.rootGetters访问到全局的getter。
14. 组件中如何使用各个属性
- 直接通过
this.$store.getters和this.$store.state来访问模块中的getter和state。 - 直接通过
this.$store.commit('mutationA',data)提交模块中的mutation。 - 直接通过
this.$store.dispatch('actionA,data')提交模块中的action。
15.带命名空间模块内提交全局mutation和action
将 { root: true } 作为第三参数传给 dispatch 或 commit 即可。
- this.$store.dispatch('actionA', null,
{ root: true }) - this.$store.commit('mutationA', null,
{ root: true })
16.命名空间的模块内注册全局action
actions: {
actionA: {
root: true,
handler (context, data) { ... }
}
}