Научит вас, как использовать Vuex, учебник, понятный обезьянам

Vue.js
Научит вас, как использовать Vuex, учебник, понятный обезьянам

Зачем делать эту коллекцию? На рынке так много туториалов по vuex, и даже vuex инкапсулировали какие-то великие боги.Ну, хватит чепухи, давайте вкратце представим vuex, что это такое?

Первый шаг, если вы хотите понять технологию, зайдите на его официальный сайт, чтобы увидеть, да, зайдите на официальный сайт, что бросается в глаза, так это «что такое vuex»:

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

Первый шаг, понять Vuex

🤯 Представьте сценарий

Если в вашем проекте много страниц (компонентов/представлений) и между страницами существует многоуровневая вложенность, в настоящее время, если всем этим страницам необходимо совместно использовать состояние, возникнут следующие две проблемы:

  • Несколько представлений зависят от одного и того же состояния
  • Действия из разных представлений должны изменять одно и то же состояние

🤪 Двигайте головой и вы придумаете решение вышеописанным методам:

  • Для первой проблемы, если это многоуровневая вложенная связь, вы можете использовать компонент родитель-потомок для передачи параметров для ее решения, хотя это немного хлопотно, но, к счастью, ее можно решить; для одноуровневых компонентов или компонентов с более сложные отношения, решить сложно, хотя можно решить разными способами, это действительно неэлегантно, а когда проект разрастется, код станет горой дерьма, что реально раздражает.
  • Для второй проблемы вы можете использовать компоненты «родитель-потомок» для прямой ссылки или через события для изменения или синхронизации нескольких копий состояния.Этот режим очень хрупок, часто затрудняет поддержку кода, а также делает код горой. дерьма.

😇 На данный момент, так как я подумал об этом здесь, что, если я передумаю:

  • Извлеките одно и то же состояние, от которого должен зависеть каждый компонент, и используйте шаблон singleton для глобального управления им.
  • В этом режиме любой компонент может напрямую обращаться к этому состоянию, или при изменении состояния все компоненты обновляются.

👶 В это время родился Vuex!

Это основная идея Vuex, заимствованная у Flux и Redux. В отличие от других паттернов, Vuex — это библиотека управления состоянием, специально разработанная для Vue, чтобы использовать механизм ответа на детализированные данные Vue.js для эффективного обновления состояния.

😨 Далее вы увидите схему цикла использования vuex на официальном сайте ниже (не беда, если вы ее не понимаете):

🤩 Когда мне следует использовать vuex?

  • Эта проблема зависит от человека. Если вам не нужно разрабатывать крупномасштабное одностраничное приложение, вам вообще не нужно использовать vuex. Например, у вас есть две или три страницы. После использования vuex, добавленных файлов больше, чем ваших текущих страниц. , то в этом нет необходимости.
  • Если ваш проект достигает масштаба приложения от среднего до крупного, вы, вероятно, задумаетесь о том, как лучше управлять состоянием вне компонентов, и Vuex станет естественным выбором.

🤔 Это краткое введение в vuex. Теперь давайте использовать его вместе!

Второй шаг, установка

Войдите в проект, введите инструкции по установке в командной строке и нажмите Enter.

npm install vuex --save

Затем настройте vuex, чтобы он работал: создайте папку хранилища по пути src, а затем создайте файл index.js со следующим содержимым:

import Vue from 'vue';
import Vuex from 'vuex';

Vue.use(Vuex);

const store = new Vuex.Store({
    state: {
        // 定义一个name,以供全局使用
        name: '张三',
        // 定义一个number,以供全局使用
        number: 0,
        // 定义一个list,以供全局使用
        list: [
            { id: 1, name: '111' },
            { id: 2, name: '222' },
            { id: 3, name: '333' },
        ]
    },
});

export default store;

Измените main.js:

import Vue from 'vue';
import App from './App';
import router from './router';
import store from './store'; // 引入我们前面导出的store对象

Vue.config.productionTip = false;

new Vue({
    el: '#app',
    router,
    store, // 把store对象添加到vue实例上
    components: { App },
    template: '<App/>'
});

Наконец, измените App.vue:

<template>
    <div></div>
</template>

<script>
    export default {
        mounted() {
            // 使用this.$store.state.XXX可以直接访问到仓库中的状态
            console.log(this.$store.state.name); 
        }
    }
</script>

На этом этапе запустите проектnpm run dev, вы можете вывести значение имени, которое мы только что определили в хранилище на консоли.

  • 🤖 Официальная рекомендация 1:

Официально рекомендуется размещать указанные выше операции this.$store.state.XXX в вычисляемом свойстве.Конечно, я также рекомендую вам использовать его таким образом, чтобы сделать ваш код более элегантным, например:

export default {
    mounted() {
        console.log(this.getName); 
    },
    computed:{
        getName() {
            return this.$store.state.name;
        }
    },
}

В это время можно получить тот же эффект, что и выше.

  • 🤖 Официальная рекомендация 2:

Раздражает ли каждый раз писать this.$store.state.XXX, а если вы действительно не хотите писать эту штуку, конечно есть решение, вроде следующего:

<script>
import { mapState } from 'vuex'; // 从vuex中导入mapState
export default {
    mounted() {
        console.log(this.name);
    },
    computed: {
        ...mapState(['name']), // 经过解构后,自动就添加到了计算属性中,此时就可以直接像访问计算属性一样访问它
    },
}
</script>

Вы даже можете дать ему псевдоним при деструктуризации, например:

...mapState({ aliasName: 'name' }),  // 赋别名的话,这里接收对象,而不是数组

🤗 На этом работа по установке vuex и инициализации завершена, теперь вы можете легко получить доступ к статусу репозитория в любом месте проекта

Третий шаг, разбираемся с декоратором: Getter

Когда вы видите это, это доказывает, что вы отлично создали проект vue на предыдущем шаге и установили в него vuex!

хорошо! Далее мы представляем «инструмент украшения» для операций чтения --- Getter

  • 🤨 Представьте себе сценарий, вы вывели название в магазине на странице, и отображается много страниц, в это время приходит продакт-менеджер что-то искать 😡:

  • Менеджер по продукту: Все имена должны начинаться с «привет»!

  • Почему я?

  • Менеджер по продукту: Нужно ли спрашивать, почему?

  • Я: Хорошо, добавлю!

На данный момент ваша первая мысль состоит в том, как его добавить, эмм... На каждой странице используйте this.$store.state.name, чтобы получить значение, просмотреть его и добавить «привет» впереди.

🤦🏻‍♂️ Неправильно! Это плохо по следующим причинам:

  • Во-первых, если вы используете name на трех страницах A, B и C, вам нужно изменить все три страницы A, B и C. Для нескольких страниц вам нужно добавить этот метод много раз, что приведет к код Избыточность плохая;
  • Во-вторых, если в следующий раз, когда продакт-менеджер попросит заменить «привет» на «бля», придется заново менять все три страницы, тогда можно только оплеуху…

👏🏻 Изучив вышеперечисленные уроки, у вас появится новая идея: мы можем напрямую выполнять некоторые операции или обработку имени в магазине, чтобы решить проблему из первоисточника! Так как это должно быть написано? В это время выходит добытое оружие, которое будет представлено на этот раз!

🤡 Как им пользоваться? Без глупостей, покажи код!

Во-первых, добавьте свойство getters в объект хранилища.

import Vue from 'vue';
import Vuex from 'vuex';

Vue.use(Vuex);

const store = new Vuex.Store({
    state: {
        name: '张三',
        number: 0,
        list: [
            { id: 1, name: '111' },
            { id: 2, name: '222' },
            { id: 3, name: '333' },
        ]
    },
    // 在store对象中增加getters属性
    getters: {
        getMessage(state) { // 获取修饰后的name,第一个参数state为必要参数,必须写在形参上
            return `hello${state.name}`;
        }
    },
});

export default store;

Использование в компоненте:

export default {
    mounted() {
        // 注意不是$store.state了,而是$store.getters
        console.log(this.$store.state.name);
        console.log(this.$store.getters.getMessage);
    }
}

Затем посмотрите на консоль:

Без проблем

🤖 Официальный совет: Раздражает ли каждый раз писать this.$store.getters.XXX? Что делать, если вы действительно не хотите писать это? Конечно, есть решения. Официальное предложение состоит в том, что мы можем использовать mapGetters для деконструкции их в вычисляемые свойства, точно так же, как использование mapState То же самое, вы можете использовать этот вызов напрямую, как показано ниже:

<script>
import { mapState, mapGetters } from 'vuex';
export default {
    mounted() {
        console.log(this.name);
        console.log(this.getMessage);
    },
    computed: {
        ...mapState(['name']),
        ...mapGetters(['getMessage']),
    },
}
</script>

На этом этапе вы можете получить тот же эффект, что и раньше.

Конечно, как и в случае с mapState, вы также можете использовать псевдонимы и псевдонимы, как показано ниже:

...mapGetters({ aliasName: 'getMessage' }),  // 赋别名的话,这里接收对象,而不是数组

🤗 Хорошо, когда вы видите это, вы успешно использовали геттеры, а также можете понять, когда вам следует использовать геттеры, вы можете получить к ним доступ через вычисляемые свойства (кешированные), или через методы (без кэширования), вы даже можете вызывать геттеры метод в методе геттеров.Конечно, вы также можете использовать mapGetters для деконструкции вычисляемых свойств, таких как состояние, поэтому вы можете легко использовать геттеры!

😎 У нас есть "родное чтение (состояние)" и "модифицированное чтение (геттеры)" для операции чтения значения. Далее мы расскажем, как изменить значение!

Шаг 4, узнайте, как изменить значение: Мутация

🤗 Хорошо! Прежде всего, поздравляю с этим. Пока мы успешно получили доступ к значению в хранилище. Далее я расскажу, как изменить значение в состоянии.

  • Когда дело доходит до изменения значения, некоторые учащиеся могут написать так:
// 错误示范
this.$store.state.XXX = XXX;

🤪 Прежде всего, поясняю: это неправильное написание! Это неправильное написание! Это неправильное написание!

Почему приведенное выше написание неверно? Потому что склад этого магазина довольно странный, вы можете взять его как хотите, но вы не можете изменить его по своему желанию.Приведу пример:

🤔 Если вы открываете WeChat Moments и видите, что ваш друг разместил сообщение, но в сообщении есть опечатка, что делать? Можете ли вы помочь ему изменить это? Конечно, нет! Мы можем только уведомить его, чтобы он изменил его сам, потому что это чужой круг друзей, вы не имеете права управлять им, только он может управлять им.Так же и в vuex мы не можем напрямую изменить значение на складе, мы должны используйте его с методом vuex, чтобы изменить, на этот раз, дебют мутации!

😬 После четкого объяснения проблемы мы готовы выполнить эффект: сначала мы выводим значение по умолчанию числа 0 в состоянии, а затем мы меняем значение числа 0 по умолчанию, отправив Mutations в компоненте vue на желаемое значение. изменить, а затем вывести его, чтобы вы могли легко попрактиковаться в использовании мутаций. Без лишних слов, давайте кодировать.

  • Изменить store/index.js
import Vue from 'vue';
import Vuex from 'vuex';

Vue.use(Vuex);

const store = new Vuex.Store({
    state: {
        name: '张三',
        number: 0,
    },
    mutations: { // 增加nutations属性
        setNumber(state) {  // 增加一个mutations的方法,方法的作用是让num从0变成5,state是必须默认参数
            state.number = 5;
        }
    },
});

export default store;
  • Изменить App.vue
<script>
export default {
    mounted() {
        console.log(`旧值:${this.$store.state.number}`);
        this.$store.commit('setNumber');
        console.log(`新值:${this.$store.state.number}`);
    },
}
</script>
  • Запустите проект и просмотрите консоль:

  • 🤡 Вышеупомянутый простой способ реализовать мутации без передачи параметров, что, если мы хотим передать нефиксированные параметры? Далее научим вас решать

  • Изменить store/index.js

import Vue from 'vue';
import Vuex from 'vuex';

Vue.use(Vuex);

const store = new Vuex.Store({
    state: {
        name: '张三',
        number: 0,
    },
    mutations: {
        setNumber(state) {
            state.number = 5;
        },
        setNumberIsWhat(state, number) { // 增加一个带参数的mutations方法
            state.number = number;
        },
    },
});

export default store;
  • Изменить App.vue
<script>
export default {
    mounted() {
        console.log(`旧值:${this.$store.state.number}`);
        this.$store.commit('setNumberIsWhat', 666);
        console.log(`新值:${this.$store.state.number}`);
    },
}
</script>
  • Запустите проект и просмотрите консоль:

нет проблем!

  • Примечание: Хотя описанный выше метод передачи параметров может достичь цели, это не рекомендуется.Официальная рекомендация - передавать объект, который выглядит более красиво.Вы можете назвать объект по желанию, но мы обычно называем его полезной нагрузкой. Код выглядит следующим образом:

  • Изменить store/index.js

mutations: {
    setNumber(state) {
        state.number = 5;
    },
    setNumberIsWhat(state, payload) { // 增加一个带参数的mutations方法,并且官方建议payload为一个对象
        state.number = payload.number;
    },
},
  • Изменить App.vue
<script>
export default {
    mounted() {
        console.log(`旧值:${this.$store.state.number}`);
        this.$store.commit('setNumberIsWhat', { number: 666 });  // 调用的时候也需要传递一个对象
        console.log(`新值:${this.$store.state.number}`);
    },
}
</script>
  • На данный момент вы можете получить тот же эффект, что и раньше, и код стал более красивым!

😱 这里说一条重要原则:Mutations里面的函数必须是同步操作,不能包含异步操作!(别急,后面会讲到异步)

😱 这里说一条重要原则:Mutations里面的函数必须是同步操作,不能包含异步操作!(别急,后面会讲到异步)

😱 这里说一条重要原则:Mutations里面的函数必须是同步操作,不能包含异步操作!(别急,后面会讲到异步)

Хорошо, запомните этот важный принцип, давайте добавим небольшую хитрость:

  • 🤖 Официальное предложение: Как и в случае с mapState и mapGetters в начале, мы можем использовать mapMutations вместо this.$store.commit('XXX') в компонентах, не правда ли, это очень удобно?
<script>
import { mapMutations } from 'vuex';
export default {
    mounted() {
        this.setNumberIsWhat({ number: 999 });
    },
    methods: {   // 注意,mapMutations是解构到methods里面的,而不是计算属性了
        ...mapMutations(['setNumberIsWhat']),
    },
}
</script>
  • На этом этапе вы можете получить тот же эффект, что и раньше, и код станет немного красивее!

  • Конечно, вы также можете дать ему псевдоним, взять псевдоним, например:

methods:{
    ...mapMutations({ setNumberIsAlias: 'setNumberIsWhat' }),   // 赋别名的话,这里接收对象,而不是数组
}
  • 🤔 ОК, введение в Mutation примерно такое, кроме того, вы также знаете, как писать с параметрами или без при определении метода мутации, и, выслушав официальный совет, используйте mapMutations для деконструкции методов внутри вашего компонента, поэтому что вы можете Вы можете использовать метод мутаций очень просто!

  • 🤪 Как упоминалось выше, Мутации могут выполнять только синхронные операции, поэтому давайте начнем следующий раздел и посмотрим, на что следует обратить внимание при использовании Действия для асинхронных операций!

Пятый шаг, понимание асинхронных операций: Действия

😆 Хорошо! В этом разделе мы научимся использовать действия. Смысл действий состоит в том, чтобы предположить, что у вас есть асинхронные операции при изменении состояния. Автор vuex не хочет, чтобы вы помещали асинхронные операции в мутации, поэтому они создали для вас область ставить асинхронные операции.Действия, это и есть Действия

😛 Перейдем непосредственно к предыдущему коду

  • Изменить store/index.js
const store = new Vuex.Store({
    state: {
        name: '张三',
        number: 0,
    },
    mutations: {
        setNumberIsWhat(state, payload) {
            state.number = payload.number;
        },
    },
    actions: {   // 增加actions属性
        setNum(content) {  // 增加setNum方法,默认第一个参数是content,其值是复制的一份store
            return new Promise(resolve => {  // 我们模拟一个异步操作,1秒后修改number为888
                setTimeout(() => {
                    content.commit('setNumberIsWhat', { number: 888 });
                    resolve();
                }, 1000);
            });
        }
    }
});
  • Изменить App.vue
async mounted() {
    console.log(`旧值:${this.$store.state.number}`);
    await this.$store.dispatch('setNum');
    console.log(`新值:${this.$store.state.number}`);
},
  • Запустите проект и просмотрите консоль:

🤓 Глядя на пример, вы понимаете, что действие заключается в отправке мутации, все асинхронные операции перевариваются в действии, и, наконец, мутация отправляется.

😼 Конечно, вы можете имитировать мутацию для передачи параметров, например:

  • Изменить store/index.js
actions: {
    setNum(content, payload) {   // 增加payload参数
        return new Promise(resolve => {
            setTimeout(() => {
                content.commit('setNumberIsWhat', { number: payload.number });
                resolve();
            }, 1000);
        });
    },
}
  • Изменить App.vue
async mounted() {
    console.log(`旧值:${this.$store.state.number}`);
    await this.$store.dispatch('setNum', { number: 611 });
    console.log(`新值:${this.$store.state.number}`);
},
  • Запустите проект, проверьте консоль

Нет проблем!

  • 🤖 Официальное предложение 1: Если вы не хотите использовать this.$store.dispatch('XXX') для постоянного вызова действий, вы можете использовать mapActions для деконструкции связанных действий в методы и вызывать их напрямую с помощью этого:
<script>
import { mapActions } from 'vuex';
export default {
    methods: {
        ...mapActions(['setNum']),   // 就像这样,解构到methods中
    },
    async mounted() {
        await this.setNum({ number: 123 });  // 直接这样调用即可
    },
}
</script>

Конечно, вы также можете использовать псевдонимы и прозвища, например:

...mapActions({ setNumAlias: 'setNum' }),   // 赋别名的话,这里接收对象,而不是数组
  • 🤖 Официальное предложение 2: В действиях в store/index.js формальные параметры метода могут напрямую деконструировать коммит, что может облегчить последующие операции:
actions: {
    setNum({ commit }) {   // 直接将content结构掉,解构出commit,下面就可以直接调用了
        return new Promise(resolve => {
            setTimeout(() => {
                commit('XXXX');  // 直接调用
                resolve();
            }, 1000);
        });
    },
},
  • 🤠 Хорошо, увидев это, вы должны понимать положение действия в vuex. Когда использовать действие, а когда не использовать его, у вас должно быть собственное суждение. Самое важное условие суждения - не является ли операция, которую я хочу сделать, асинхронной. , что является сущностью существования действия. Конечно, не путайте действие и мутацию, действие на самом деле является верхним уровнем мутации, после обработки некоторых асинхронных операций в действии последующая модификация состояния передается мутации.

Шаг 6. Резюме

🤗 Хорошо! Общее объяснение vuex находится здесь. Вы должны быть знакомы с vuex, когда увидите его здесь. Вы установите его, настроите, прочитаете значение состояния и даже измените чтение (Getter), а затем измените значение. внутри.(Мутация), если у вас есть асинхронные операции и вам нужно модифицировать состояние, то вам нужно использовать Action, чтобы вы могли использовать vuex в своем проекте! Ну давай же! 🤔