【问题标题】:What is the best way to save async data in Vue?在 Vue 中保存异步数据的最佳方法是什么?
【发布时间】:2019-01-16 07:20:53
【问题描述】:

我有以下商店模块:

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
            }
        })
    }
}

【问题讨论】:

  • 您应该简单地使用 Computed ,因为它会在商店中的值发生变化时发生变化

标签: javascript vue.js vuejs2 async-await vuex


【解决方案1】:

由于您已经了解商店映射,我想您尝试使用某种编辑表单,您需要在其中需要从数据库中获取的实际数据以及更改这些数据以便稍后将其发送回数据库的能力。

您不需要 getter 来简单地引用商店项目。在你的组件中使用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 选项),您可以在组件中安全地修改它,而不会对商店引用产生任何影响。

附:不得不提的是,在这个实现中,如果你想对 edit 对象中的字段产生反应,那么你需要在每个字段更新时更新整个 edit 对象,如下所示:this.edit = {...this.edit, [prop]: value}。但如果你想让它成为自然的 Vue 方式,那么首先你需要用实际的对象结构初始化 edit,并在 user 的观察器中执行类似 Object.assign(this.edit, user) 的操作。

【讨论】:

  • 感谢您的解释!现在的问题是何时使用store.subscribe()?你能给我举个例子吗?
  • 当您需要了解任何存储突变时,您可以使用它。说实话,我从来没有使用过它。假设当您需要在许多商店项目可能发生变化时做出反应时它会有所帮助,但我通常只是将它们捆绑在一个对象中并观察它。
  • 明白了!谢谢
【解决方案2】:

最好使用computed 属性来访问存储数据并使其保持反应性。 可以像在共享片段中一样使用mapGetters 创建计算属性,但是,考虑到getter 只是从状态返回user,我认为您根本不需要getter,您可以简单地使用mapState helper 从状态映射值。通过这种方式,组件将被简化为如下所示:

import { mapState } from 'vuex'

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

通过上述方法,您可以在组件的方法中将用户引用为this.user,或者在组件的模板中简单地引用为user。此外,由于 getter 不再使用,您可以从商店中删除 getter 定义(除非您在其他任何地方使用它)。

【讨论】:

    猜你喜欢
    • 2018-06-16
    • 2020-11-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-19
    • 2011-01-16
    • 2015-07-13
    • 2013-05-17
    相关资源
    最近更新 更多