5x1 精读Vue官方文档 - 状态管理

850 阅读4分钟

精读 Vue 官方文档系列 🎉

类 Flux 状态管理的官方实现

vuexredux 都是对 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-titleblog-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: {}
        }
    }
});

下图是对上述方式的图解:

image.png

vuex 本质也是应用了此种思想,vuex 会将需要跨组件共享的数据从 Vue 应用中提取出来,作为一个全局的状态进行管理,并且进一步规定,组件不允许直接变更属于 store 实例的 state,而应执行 action 来管理,而 action 的触发,应该要通过 dispatch 触发事件通知。这样我们最终就实现了符合 Flux 架构并通过单向数据流的方式来更新应用视图。

实际中的 vuex 往往会更复杂些,例如为了更合理的管理状态变更,action 又分为同步更新状态的 mutation 与异步更新状态的 action 两种,这样的好处就是将异步与同步操作区别开来,避免破坏 muation 的封装性,例如一些需要同步执行的功能,比如日志记录等,所以不能直接含有副作用。

vuexvue-devtools 的结合,为我们提供了更强大的调试能力:

  • 能够记录所有 store 中发生的 state 变更。
  • 结合 vue-devtools 工具可以保存状态快照、历史回滚/时光旅行。

Vue3 反应式编程中是否还需要 Vuex ?

个人答案。小型应用可以使用 Vue Composition API 来自定义状态管理,实际上早在 Vue2.x 版本中 Vue 就已经暴露了其底层的响应式系统,例如 Vue.observable API。这也是为什么我认为 Vuex 依然是需要的,因为它的稳定性、扩展性、安全性等非常符大型应用的状态管理,对于大量状态的管理,个人封装的状态管理库,将很难满足需求的迭代。

并且,Vuex 也并非是孤立存在的,其周边生态相当丰富,例如一些数据持久化的插件、结合 vue-devtools 可以获得更好的调试体验。