Хотите облегченную альтернативу Vuex для управления состоянием в веб-приложениях Vue.js?

Vue.Observable можно использовать в качестве хранилища состояний вместо Vuex в простых приложениях. Вот простой способ начать:

Версия 2.6.0 Vue.js добавила Vue.Observable. Это функция, которая возвращает реактивный экземпляр данного объекта. В Vue объекты не являются автоматически реактивными. Это означает, что если мы хотим реагировать на изменение свойств объекта, нам нужно проделать дополнительную работу. 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, является реактивным!

Реактивность через данные()

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 функциях каждого компонента быстро разваливается. В частности, это становится проблемой, когда данные должны передаваться между одноуровневыми компонентами.

Компонент с данными передает их родительскому компоненту через события, а затем родительский компонент передает их родственному компоненту через реквизит? Даже в простых случаях это сразу запах кода, а не отличный опыт разработки. Он объединяет компоненты, его сложно тестировать, он подвержен ошибкам, неудобен в сопровождении и просто сбивает с толку.

Здесь на помощь приходят государственные магазины.

Государственное управление

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, происходит важная часть. Геттеры и мутации — это то, как мы читаем и обновляем состояние. Действия — это то, куда идут асинхронные вызовы, а именно запросы API. Действия совершают изменения, потенциально основанные на результатах запросов API.

компонент.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 и использовать одно и то же состояние. Нет необходимости использовать реквизит/события для передачи данных.

Дополнительный совет для компонентов, которым не нужны все геттеры или вычисляемое значение:

компонент.js

computed() {
    // ...getters <- instead of this, do this:
    radius() {
        return getters.radius;
    },
    diameter() {
        return getters.radius * 2;
    }
    // this component doesn't need color
}

Первоначально опубликовано на https://austincooper.dev 9 августа 2019 г.