1、用过 module,项目规模变大之后,单独一个 store 对象会过于庞大臃肿,通过模块方式可以拆分开来便于维护
2、可以按之前规则单独编写子模块代码,然后在主文件中通过modules
选项组织起来:createStore({modules:{...}})
。
3、不过使用时要注意访问子模块状态时需要加上注册时模块名:store.state.a.xxx
,但同时getters
、mutations
和actions
又在全局空间中,使用方式和之前一样。如果要做到完全拆分,需要在子模块加上namespace
选项,此时再访问它们就要加上命名空间前缀。
很显然,模块的方式可以拆分代码,但是缺点也很明显,就是使用起来比较繁琐复杂,容易出错。而且类型系统支持很差,不能给我们带来帮助。pinia 显然在这方面有了很大改进,是时候切换过去了。
修改状态只能是mutations
,actions
只能通过提交mutation
修改状态即可
官方文档说:更改 Vuex 的 store 中的状态的唯一方法是提交 mutation
,mutation
非常类似于事件:每个 mutation
都有一个字符串的类型 (type)**和一个** 回调函数 (handler) 。Action
类似于 mutation
,不同在于:Action
可以包含任意异步操作,但它不能修改状态, 需要提交mutation
才能变更状态。
因此,开发时,包含异步操作或者复杂业务组合时使用 action;需要直接修改状态则提交 mutation。但由于 dispatch 和 commit 是两个 API,容易引起混淆,实践中也会采用统一使用 dispatch action 的方式。
调用 dispatch 和 commit 两个 API 时几乎完全一样,但是定义两者时却不甚相同,mutation 的回调函数接收参数是 state 对象。action 则是与 Store 实例具有相同方法和属性的上下文 context 对象,因此一般会解构它为{commit, dispatch, state}
,从而方便编码。另外 dispatch 会返回 Promise 实例便于处理内部异步结果。
实现上 commit(type)方法相当于调用options.mutations[type](state)
;dispatch(type)
方法相当于调用options.actions[type](store)
,这样就很容易理解两者使用上的不同了。
如何从零写一个 vuex?思路是什么?
- 官方说
vuex
是一个状态管理模式和库,并确保这些状态以可预期的方式变更。可见要实现一个vuex
:- 要实现一个
Store
存储全局状态 - 要提供修改状态所需 API:
commit(type, payload)
,dispatch(type, payload)
- 要实现一个
- 实现
Store
时,可以定义 Store 类,构造函数接收选项 options,设置属性 state 对外暴露状态,提供 commit 和 dispatch 修改属性 state。这里需要设置 state 为响应式对象,同时将 Store 定义为一个 Vue 插件。 commit(type, payload)
方法中可以获取用户传入mutations
并执行它,这样可以按用户提供的方法修改状态。dispatch(type, payload)
类似,但需要注意它可能是异步的,需要返回一个 Promise 给用户以处理异步结果。
1 |
|
vuex 如何监听数据的变化?
可以通过 watch 选项或者 watch 方法监听状态
可以使用 vuex 提供的 API:store.subscribe()
watch 选项方式,可以以字符串形式监听$store.state.xx
;subscribe 方式,可以调用 store.subscribe(cb),回调函数接收 mutation 对象和 state 对象,这样可以进一步判断 mutation.type 是否是期待的那个,从而进一步做后续处理。
watch 方式简单好用,且能获取变化前后值,首选;subscribe 方法会被所有 commit 行为触发,因此还需要判断 mutation.type,用起来略繁琐,一般用于 vuex 插件中。
1 |
|