Vuex一问一答(重学前端-vue篇3)

时间:2021-1-8 作者:admin

上一篇:Vuex简洁清晰指南(重学前端-vue篇2)

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.‘dispatch‘(′ACTIONNAME′,data)来提交。mutation是用this.store.`dispatch`(‘ACTION_NAME’,data)来提交。mutation是用this.store.dispatch(ACTIONNAME,data)mutationthis.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.gettersthis.$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) { ... }
    }
  }
声明:本文内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎进行举报,并提供相关证据,工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。