精读 Vue 官方文档系列 🎉
类 Flux 状态管理的官方实现
vuex 与 redux 都是对 Flux 架构的官方实现。
Flux (flʌks) 是 Facebook 用于构建客户端 Web 应用的应用程序架构。它更像是一种模式,而不是具体的框架实现。
状态管理的目标
可以跨组件进行状态共享,方便大型应用的状态管理。
如何简单理解 Vuex 的思想?
在“组件基础”一节中我们说过 data 必须是一个函数 ,这是 Vue 为了规范组件中的状态使用,避免多个组件共享同一份响应式数据。
但是反过来想,我们实际上是可以通过此种方式让多个组件共享同一份数据源。
const blogData = {
title: 'blog title',
post: 'blog content'
};
Vue.component("blog-item", {
name: 'BlogItem',
data() {
return { blogData }
}
});
Vue.component("blog-content", {
name: 'BlogContent',
data() {
return { blogData }
}
});
现在如果有其它的组件或者行为更改了 blogData 中的值,那么 blog-title 与 blog-content 都将自动地更新它们的视图。
虽然我们通过非常简单的方式实现了跨组件、多组件的数据共享,但是这也为调试带来了噩梦,因为我们的应用在任何时间、任何部分都可能会变更 blogData 的值,我们无法准确的定位正在发生变更的地方,因此也无法留下变更过的记录。
为了解决这一问题,我们必须对共享的数据进行规范,例如采用一个简单的 store 模式
var store = {
debug: true,
state: {
blogData: {
title: 'blog title',
post: 'blog content'
}
},
setBlogDataAction(newValue) {
if (this.debug) console.log('setMessageAction triggered with', newValue)
this.state.blogData = { ...this.state.blogData, ...newValue }
},
clearBlogDataAction() {
if (this.debug) console.log('clearMessageAction triggered')
this.state.message = {
title: '',
post: ''
}
}
}
现在 store 中的 state 变更,必须要基于自生的 action 去管理,这样的好处就是有一个统一的状态管理方法,我们可以在这个方法中基于状态变更的前后提供更多的扩展能力,例如记录状态变更的日志。
注意,你不应该在 action 中 替换原始的状态对象 - 组件和 store 需要引用同一个共享对象,变更才能够被观察到。
此外,每个实例/组件仍然可以拥有和管理自己的私有状态。
Vue.component("blog-item", {
name: 'BlogItem',
data() {
return {
blogData: store.state,
privateState: {}
}
}
});
Vue.component("blog-content", {
name: 'BlogContent',
data() {
return {
blogData: store.state,
privateState: {}
}
}
});
下图是对上述方式的图解:
vuex 本质也是应用了此种思想,vuex 会将需要跨组件共享的数据从 Vue 应用中提取出来,作为一个全局的状态进行管理,并且进一步规定,组件不允许直接变更属于 store 实例的 state,而应执行 action 来管理,而 action 的触发,应该要通过 dispatch 触发事件通知。这样我们最终就实现了符合 Flux 架构并通过单向数据流的方式来更新应用视图。
实际中的
vuex往往会更复杂些,例如为了更合理的管理状态变更,action 又分为同步更新状态的mutation与异步更新状态的action两种,这样的好处就是将异步与同步操作区别开来,避免破坏muation的封装性,例如一些需要同步执行的功能,比如日志记录等,所以不能直接含有副作用。
vuex 与 vue-devtools 的结合,为我们提供了更强大的调试能力:
- 能够记录所有 store 中发生的 state 变更。
- 结合
vue-devtools工具可以保存状态快照、历史回滚/时光旅行。
Vue3 反应式编程中是否还需要 Vuex ?
个人答案。小型应用可以使用 Vue Composition API 来自定义状态管理,实际上早在 Vue2.x 版本中 Vue 就已经暴露了其底层的响应式系统,例如 Vue.observable API。这也是为什么我认为 Vuex 依然是需要的,因为它的稳定性、扩展性、安全性等非常符大型应用的状态管理,对于大量状态的管理,个人封装的状态管理库,将很难满足需求的迭代。
并且,Vuex 也并非是孤立存在的,其周边生态相当丰富,例如一些数据持久化的插件、结合 vue-devtools 可以获得更好的调试体验。