Vuex 面试题(2023-09-13更新)

谈谈你对 Vuex 的理解

什么是 Vuex?

vuex 是 Vue 应用程序开发的状态管理插件,它采用集中式存储,管理应用的所有组件的状态

Vuex 解决了什么问题?

  • 多个组件依赖于同一状态时,多层嵌套的组件,传参将会非常繁琐
  • 来自不同组件的行为需要变更同一状态

核心概念

Vuex 的 5 个核心属性是什么?

  • state 数据源存放地
  • getter 计算属性
  • mutation 用于编写同步提交更改数据的方法
  • action 用于编写异步操作
  • module 模块化(分割模块)

State

怎么获取 state 中的数据?

this.$store.state.data

怎么在组件中批量使用 Vuex 的 state 数据?

使用 mapState 辅助函数,利用对象展开运算符将 state 混入 computed 中

import { mapState } from 'vuex'

export default {
  computed: {
    ...mapState({
      a: (state) => state.a,
      b: (state) => state.b
    })
  }
}

getters

怎么在组件中批量使用 Vuex 的 getter 属性?

使用 mapGetters 辅助函数

import { mapGetters } from 'vuex'

export default {
  computed: {
    ...mapGetters(['totalCount', 'totalPrice'])
  }
}

如果你想将一个 getter 属性另取一个名字,使用对象形式

...mapGetters({
  myCount: 'totalCount',
  myPrice: 'totalPrice'
})

Mutation

怎么改变其中的数据?

更改 store 中的数据,唯一方法是提交 mutation,使用 store.commit()

this.$store.commit('update')

在组件中多次提交同一个 mutation,怎么写方便?

使用 mapMutations 辅助函数

import { mapMutations } from 'vuex'

export default {
  methods: {
    ...mapMutations({
      setNumber: 'SET_NUMBER'
    })
  }
}

然后调用 this.setNumber(10) 相当于调用 this.$store.commit('SET_NUMBER', 10)


Action

怎么提交一个 action?

使用 store.dispatch

this.$store.dispatch('update')

在组件中多次提交同一个 action,怎么写方便

import { mapActions } from 'vuex'

export default {
  methods: {
    ...mapActions({
      logout: 'logout'
    })
  }
}

然后调用 this.logout() 相当于调用 this.$store.dispatch('logout')

Vuex 中 action 通常是异步的,那么如何知道 action 是什么时候结束呢?

action 函数中返回 Promise,然后用 .then 处理


其他

Vuex 中 action 和 mutation 有什么区别?

  • mutation 是同步操作,action 异步操作
  • mutation 可以直接变更状态,action 不能直接变更状态,需要提交一个 mutation
  • 两者提交方式不铜
    • mutation 使用 commit 进行提交:this.$store.commit('set_number', 10)
    • action 使用 dispatch 进行提交:this.$store.dispatch('logout')

模块化

Vuex 为什么要分模块?

由于使用单一状态树,应用的所有状态都会集中到一个对象里,当应用变得非常复杂时,store 对象就会变得相当臃肿

为了解决这个问题,vuex 允许将 store 对象分割成模块,每个模块拥有自己的属性

怎么访问模块中的 state、mutation、getter、action?

访问 state 需要加上模块的名称,访问其他属性不需要

this.$store.state.moduleName.data

命名空间

什么是命名空间?

默认情况下,模块内的 action、mutation、getters 是注册在全局命名空间的,state 除外,这样使得多个模块能对同一属性做出响应。

如果希望模块具有更高的封装度和复用性,可以通过添加 namespaced: true 的方式使其成为带命名的模块,当模块被注册后,内部属性会自动根据模块注册的路径调整命名

增加一个 moduleA 的文件,编写如下代码:

const mutation = {
  set_number: (state, data) => {
    state.number = data
  }
}

export default {
  namespaced: true,
  mutations
}

调用命名空间模块的方法:

this.$store.commit('moduleA/set_number', 10)

怎么在带命名空间的模块内,访问全局的 mutation 或 action?

{root: true} 作为第三参数传给 dispatchcommit 即可

new Vuex.Store({
  modules: {
    foo: {
      namespaced: true,
      actions: {
        fooAction({ dispatch, commit }) {
          dispatch('someAction', null, { root: true })

          commit('someMutation', null, { root: true })
        }
      }
    }
  }
})

怎么在带命名空间的模块内,注册全局 action?

在 action 函数中添加 root: true,并将这个函数定义放在 handler

new Vuex.Store({
  modules: {
    foo: {
      namespaced: true,
      actions: {
        fooAction: {
          root: true,
          handler(context, data) {
            //...
          }
        }
      }
    }
  }
})

createNamespacedHelpers 是做什么的?

当时用 mapState、mapGetters、mapMutations、mapActions 这些函数来绑定来命名空间的模块是,写起来可能会比较繁琐,
如果是多层嵌套的 module,将会更为繁琐:

computed: {
  ...mapState({
    a: state => state.module.a,
    b: state => state.module.b
  }),
  ...mapGetters([
    'module/totalCount',
    'module/totalPrice'
  ])
},
methods: {
  ...mapActions({
    logout: 'module/logout'
  })
}

对于这种情况,可以将模块的空间字符串作为第一个参数传给上述函数,这样就会自动将该模块绑定到上下文中,简化如下:

computed: {
  ...mapState('module', {
    a: state => state.a,
    b: state => state.b
  }),
  ...mapGetters('module', [
    'totalCount',
    'totalPrice'
  ])
},
methods: {
  ...mapActions('module',{
    logout: 'logout'
  })
}

还可以使用 createNamespacedHelpers 创建基于某个命名空间的辅助函数:

import { createNamespacedHelpers } from 'vuex'

const { mapState, mapActions } = createNamespacedHelpers('module')

export default {
  computed: {
    ...mapState({
      a: (state) => state.a,
      b: (state) => state.b
    })
  },
  methods: {
  ...mapActions([
    logout: 'logout'
  ])
  }
}

其他

Vuex 和 localStorage 的区别?

  • localStorage 数据存放在硬盘文件上,读写硬盘开销高;Vuex 数据存放在内存中,读写开销小,读写速度也会比 localStorage 快很多
  • vuex 是状态管理,应该将依赖性比较高的变量数据存放到这里,方便查找维护,比较规范
  • vuex 的数据是响应式的

Vuex 页面刷新丢失怎么解决?

需要做数据持久化

  • 可以使用本地存储的方法来保存数据,设计存储方案
  • 也可以使用第三方插件:vuex-persistvuex-persistedstate

Vuex 的严格模式是什么?有什么作用?怎么开启?

在严格模式,发生了状态变更且不是有 mutation 函数引起的,就会抛出错误,这样能保证所有的状态变更都能被调试工具跟踪到
在 Vuex.Store 构造器选项中开启:

const store = new Vuex.Store({
  strict: true
})
posted @ 2021-08-09 13:33  时光凉忆  阅读(1076)  评论(0编辑  收藏  举报