内置插件
Vuex支持使用插件来扩展状态管理功能。使用new Vuex.Store(options)
时会执行以下代码:
const {
plugins = [] // 插件列表
} = options
// ...
plugins.forEach(plugin => plugin(this))
// 安装devtools插件
if (Vue.config.devtools) {
devtoolPlugin(this)
}
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
所有的插件都是一个函数,通过options.plugins
传入插件列表,实例化时会遍历插件列表,传入当前实例执行插件。同时,在开启了调试工具的情况下,Vuex
会自动安装devtoolPlugin
插件。另外,Vuex
还提供了一个Logger
插件,用于打印状态变更日志。默认情况下是不安装的,需要手动导入并安装。
import createLogger from 'vuex/dist/logger'
const store = new Vuex.Store({
plugins: [createLogger()]
})
1
2
3
4
2
3
4
本文将讲解Vuex
内置的devtoolPlugin
和Logger
如何实现,进而理解Vuex
插件的使用方式。
# devtoolPlugin插件
devtoolPlugin插件用于集成Vue Devtools
,安装此插件后可以在Vue Devtools
中查看Vuex状态变化过程。
devtoolPlugin插件定义的文件在/plugins/devtool.js
中。
const devtoolHook =
typeof window !== 'undefined' &&
window.__VUE_DEVTOOLS_GLOBAL_HOOK__ // 获取devtools的钩子
// 开发者工具插件
export default function devtoolPlugin(store) {
if (!devtoolHook) return
store._devtoolHook = devtoolHook // 给store添加_devtoolHook属性
devtoolHook.emit('vuex:init', store) // 触发vuex:init事件
// 监听vuex:travel-to-state事件
devtoolHook.on('vuex:travel-to-state', targetState => {
store.replaceState(targetState)
})
// 订阅mutation
store.subscribe((mutation, state) => {
devtoolHook.emit('vuex:mutation', mutation, state)
})
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
devtoolHook
:Vue Devtools
的钩子,当window.__VUE_DEVTOOLS_GLOBAL_HOOK__
存在时,表示Vue Devtools
已安装。
- 实例化时触发
vuex:init
事件,将当前实例store
传入。 - 监听
vuex:travel-to-state
事件,将传入的targetState
替换当前实例store
的state
。 - 订阅
mutation
,将mutation
和state
传入,触发vuex:mutation
事件。
# Logger插件
Logger插件定义在/plugins/logger.js
文件中。
其内部是一个工厂函数,参数定义和说明如下:
export default function createLogger({
collapsed = true, // 自动展开记录的mutation
// 需要被记录的mutation过滤器
// 接收当前触发的mutation,上一次的state和当前state
filter = (mutation, stateBefore, stateAfter) => true,
transformer = state => state, // 在开始记录之前返回的state
mutationTransformer = mut => mut, //格式化要记录的mutation格式
logger = console // 日志记录器实现,默认值console
} = {}) {
return store => {
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
createLogger
接收一些配置,并根据配置生成一个插件函数,供Vuex
实例化时使用。返回的插件函数会接收一个store
实例,定义如下:
return store => {
// 记录上一次state
let prevState = deepCopy(store.state)
// 定于mutation订阅
store.subscribe((mutation, state) => {
if (typeof logger === 'undefined') { // logger未定义,则不记录日志
return
}
// 记录当前的state
const nextState = deepCopy(state)
if (filter(mutation, prevState, nextState)) { // 需要记录
const time = new Date() // 时间
// 格式化后的时间 @00:00:00.000
const formattedTime = ` @ ${pad(time.getHours(), 2)}:${pad(time.getMinutes(), 2)}:${pad(time.getSeconds(), 2)}.${pad(time.getMilliseconds(), 3)}`
const formattedMutation = mutationTransformer(mutation) //格式化后的mutation
const message = `mutation ${mutation.type}${formattedTime}` // 日志消息
// 日志分组
const startMessage = collapsed
? logger.groupCollapsed
: logger.group
// render
try {
// 记录日志
startMessage.call(logger, message)
} catch (e) {
console.log(message)
}
// 记录日志
logger.log('%c prev state', 'color: #9E9E9E; font-weight: bold', transformer(prevState)) // 上一次state
logger.log('%c mutation', 'color: #03A9F4; font-weight: bold', formattedMutation) // 格式化后的mutation
logger.log('%c next state', 'color: #4CAF50; font-weight: bold', transformer(nextState)) // 格式化后的state
try {
// 分组结束
logger.groupEnd()
} catch (e) {
logger.log('—— log end ——')
}
}
// 更新上一次的state
prevState = nextState
})
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
处理的过程如下:
- 保存上一次的state,保存是方式是使用
deepCopy
函数,将store.state
深拷贝一份,保存到prevState
中。初始化时,prevState
为store.state
。 - 订阅
mutation
,在mutation
触发时- 获取新的state
- 如果未指定日志记录的方法,则不记录日志。(默认是
console
) - 根据传入的
filter
过滤器判断当前日志是否需要记录(默认是记录),需要记录则执行后续的操作 - 生成时间和日志分组名称信息
- 尝试输出日志分组标记,发生异常时则直接输出分组名称
- 分别输出上一次state、
mutation
执行信息和当前state。 - 分组结束
- 将上
prevState
设置成当前的state
,即prevState = nextState
。
以上就是Vuex
提供的两个内置插件的实现,基本的使用就是通过订阅mutation
,在mutation
触发时,做相关的操作或记录。
最近更新: 2024/07/01, 18:59