发布于 2026-01-06 1 阅读
0

使用 Vue Observable 作为状态存储

使用 Vue Observable 作为状态存储

原文链接:https://austincooper.dev/2019/08/09/vue-observable-state-store/

Vue.js 2.6.0 版本新增了 ` Vue.Observablereactive()` 函数。该函数返回给定对象的响应式实例。在 Vue 中,对象并非默认具有响应式特性。这意味着,如果我们想在对象属性发生变化时做出响应,则需要进行一些额外的工作。`reactive()` 函数让这一切变得非常简单。点击此处Vue.Observable了解更多关于响应式的信息

非反应性

const obj = {x: 0, y: 0};
export default { // Vue component
    data() { return {}; },
    method() {
        updateObj() {
            obj.x = 1;
            obj.y = 2;
        }
    }
}

在这个例子中,调用updateObj不会触发计算值的重新计算,也不会重新渲染视图。幸运的是,Vue 组件提供了该data函数。该函数返回的对象data 响应式的!

通过 data() 实现响应式

export default { // Vue component
    data() {
        return {
            obj: {x: 0, y: 0}
        };
    },
    method() {
        updateObj() {
            this.obj.x = 1;
            this.obj.y = 2;
        }
    }
}

由于结果data是响应式的,调用updateObj将导致依赖于的计算值obj重新计算,并在需要时更新视图。

从组件中突破状态

在基础组件/应用程序中,所有可变数据都存储在函数返回的对象中data。将应用程序的所有数据存储在data每个组件的函数中很快就会出现问题。尤其是在同级组件之间需要传递数据时,这个问题会更加突出。

包含数据的组件是否通过事件将数据传递给父组件,然后父组件再通过 props 将数据传递给兄弟组件?即使是简单的场景,这种做法也明显是一种代码异味,会严重影响开发体验。它会导致组件耦合、难以测试、容易出现 bug、难以维护,而且令人困惑。

这时,国营商店就派上用场了。

国家管理

Vuex 是 Vue.js 的首选状态存储插件。以下是vuejs.org对 Vuex 的描述:

Vuex 是一个用于 Vue.js 应用程序的状态管理模式和库。它为
应用程序中的所有组件提供一个集中式的状态存储,并通过规则确保状态只能
以可预测的方式进行修改。

这很棒,但 Vuex 的使用并非易事。首先,它需要作为插件添加到你的 Vue 应用中。其次,它功能非常强大,因此入门可能比较困难。最后,许多应用足够简单,并不需要 Vuex 及其所有状态管理功能。

那么,Vuex 的替代方案是什么呢?当然,答案正是本文的主题Vue.Observable

Vue.Observable 作为状态存储

最后,所有背景知识都已介绍完毕,下面介绍如何将其用作Vue.Observable状态存储。

store.js

import Vue from 'vue';
import axios from 'axios';

const state = Vue.Observable({ // this is the magic
    radius: 0,
    color: 'red'
});

export const getters {
    radius: () => state.radius,
    color: () => state.color
}

export const mutations {
    setRadius: (val) => state.radius = val,
    setColor: (val) => state.color = val
}

export const actions {
    fetchRadiusFromApi() {
        return axios
            .get('http://localhost:5001/api/radius')
            .then((res) => {
                mutations.setRadius(res.data);
            });
    },
    fetchColorFromApi() {
        return axios
            .get('http://localhost:5001/api/color')
            .then((res) => {
                mutations.setColor(res.data);
            });
    }
}

第 4 行,也就是我们声明的state地方,是关键所在。Getter 和 mutations 用于读取和更新状态。Actions 用于异步调用,也就是 API 请求。Actions 会提交 mutations,这些 mutations 可能基于 API 请求的结果。

component.vue

<template>
    <div>
        <div>Radius: {{ radius }}</div>
        <div>Color: {{ color }}</div>
        <button @:click="setRadius(0)">Reset radius</button>
        <button @:click="fetchColorFromApi">Fetch color</button>
    </div>
</template>

<script>
    import { getters, mutations, actions } from 'store.js';

    export default {
        data() { return {}; },
        computed() {
            ...getters // radius(), color()
        },
        created() {
            this.fetchRadiusFromApi(); // fetching data right away
            this.fetchColorFromApi().then(() => {
                console.log('You can chain then after actions, if you return the request');
            });
        }
        methods() {
            ...mutations, // setRadius(val), setColor(val)
            ...actions // fetchRadiusFromApi(), fetchColorFromApi()
        }
    }
</script>

总结

就是这样!任何组件都可以直接导入store.js并共享同一个状态。无需使用 props/events 来传递数据。

对于不需要所有 getter 方法或只需要计算值的组件,这里有一个额外提示:

component.js

computed() {
    // ...getters <- instead of this, do this:
    radius() {
        return getters.radius;
    },
    diameter() {
        return getters.radius * 2;
    }
    // this component doesn't need color
}
文章来源:https://dev.to/cooperaustinj/using-vue-observable-as-a-state-store-37fa