Каков наилучший способ сохранить асинхронные данные в Vue? - PullRequest
0 голосов
/ 16 января 2019

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

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.log(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
            }
        })
    }
}

Ответы [ 2 ]

0 голосов
/ 16 января 2019

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

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

0 голосов
/ 16 января 2019

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

import { mapState } from 'vuex'

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

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

...