Как лучше всего сохранить асинхронные данные во Vue?

У меня есть следующий модуль магазина:

const state = {
    user: {}
}

const mutations = {
    saveData(state, payload) {
        state.user = payload
    }
}

const actions = {
    async loadData({ commit }, payload) {
        try {
            const res = await axios.get('https://api.example.com/user/1')
            commit('saveData', res.data.data)
        } catch(e) {
            console.info(e)
        }
    } 
}

const getters = {
    getData(state) {
        return state.user
    } 
}

Как лучше всего сохранить данные в компоненте? Он использует watch

import { mapGetters } from 'vuex'

export default {
    data() {
        return {
            user: {}
        }
    },
    computed: {
        ...mapGetters({
            getData
        })
    },
    watch: {
        '$store.state.users.users'() {
            this.user = this.getData
        }
    }
}

... или store.subscribe?

import { mapGetters } from 'vuex'

export default {
    data() {
        return {
            user: {}
        }
    },
    computed: {
        ...mapGetters({
            getData
        })
    },
    created() {
        this.$store.subscribe((mutation, state) => {
            if (mutation.type === 'saveData') {
                this.user = this.getData
            }
        })
    }
}

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

Badgy 16.01.2019 08:30
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
3
1
1 944
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Предпочтительно использовать свойства computed для доступа к данным хранилища и поддержания их активности. Можно создать вычисляемое свойство с помощью mapGetters, как вы это делаете в общем фрагменте, однако, учитывая, что получатель просто возвращает user из состояния, я не думаю, что вам вообще нужен получатель, вы можете просто сопоставить значение из состояние с помощью помощника mapState. Таким образом, компонент можно упростить примерно до следующего:

import { mapState } from 'vuex'

export default {
    computed: {
        ...mapState([
            'user'
        ])
    }
}

При использовании вышеуказанного подхода вы можете ссылаться на пользователя как this.user в методах компонента или просто как на user в шаблоне компонента. Кроме того, поскольку геттер больше не используется, вы можете удалить определение получателя из хранилища (если вы не используете его где-либо еще).

Ответ принят как подходящий

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

Вам не нужен получатель, чтобы иметь простую ссылку на товар в магазине. Вам будет очень хорошо с mapState в вашем компоненте:

{
  computed: {
    ...mapState({
      user: state => state.user,
    }),
  }
}

Итак, как только user сменится в магазине, ваш компонент узнает об этом. А здесь вы можете обновить редактируемый объект. Давайте переименуем его в edit, чтобы избежать коллизии:

{
  data() {
    return {
      edit: {},
    }
  },

  computed: {
    ...mapState({
      user: state => state.user,
    }),
  },

  watch: {
    user: {
      immediate: true,
      handler(user) {
        this.edit = { ...user }
      },
    },
  },
}

Теперь edit обновляется соответствующим образом, даже если компонент был смонтирован после обновления элемента магазина (благодаря опции immediate), и вы можете безопасно изменить его в своем компоненте без какого-либо влияния на ссылку магазина.

P.S. Следует упомянуть, что в этой реализации, если вы хотите иметь реактивность для полей в объекте edit, вам необходимо обновлять весь объект edit при каждом обновлении его поля следующим образом: this.edit = {...this.edit, [prop]: value}. Но если вы хотите, чтобы это был естественный способ Vue, то сначала вам нужно инициализировать edit с реальной структурой объектов, а в наблюдателе для user выполнить что-то вроде Object.assign(this.edit, user).

Спасибо вам за разъяснение! Теперь вопрос, когда использовать store.subscribe()? Вы можете мне привести пример?

Damon 16.01.2019 10:26

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

stas.yaranov 16.01.2019 10:39

Попался! Спасибо

Damon 16.01.2019 10:43

Другие вопросы по теме