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)来提交。mutation是用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) { ... } } }