首页 > 解决方案 > 无法从商店获取计算状态的数据 - Vue

问题描述

我正在学习 Vue,并且一直在努力从计算属性中获取数据。我正在从商店中检索评论,并通过一个名为的函数进行处理,chunkify()但是我收到以下错误。

在此处输入图像描述

尽管正确计算了评论。

在此处输入图像描述

我在这里做错了什么?任何帮助将不胜感激。

主页.vue

export default {
    name: 'Home',
    computed: {
        comments() {
            return this.$store.state.comments
        },
    },
    methods: {
        init() {
            const comments = this.chunkify(this.comments, 3);
            comments[0] = this.chunkify(comments[0], 3);
            comments[1] = this.chunkify(comments[1], 3);
            comments[2] = this.chunkify(comments[2], 3);
            console.log(comments)
        },
        chunkify(a, n) {
            if (n < 2) 
                return [a];

            const len = a.length;
            const out = [];
            let i = 0;
            let size;

            if (len % n === 0) {
                size = Math.floor(len / n);
                while (i < len) {
                    out.push(a.slice(i, i += size));
                }
            } else {
                while (i < len) {
                    size = Math.ceil((len - i) / n--);
                    out.push(a.slice(i, i += size));
                }
            }
            return out;
        },
    },
    mounted() {
        this.init()
    }
}

标签: vue.jsvuex

解决方案


就像我在评论中所写的那样,OP 的问题是,当组件安装时,他正在访问一个不可用的存储属性(可能等待 AJAX 请求进入)。

我建议不要在加载组件时急切地假设数据存在,而是建议在加载属性时watch编辑和this.init()调用 store 属性。

但是,我认为这可能不是正确的方法,因为watch每次属性更改时都会调用该方法,这对于对数据进行准备工作的情况是不符合语义的。我可以提出两种我认为更优雅的解决方案。

1.数据加载时触发事件

在 Vue 中设置全局消息传递总线很容易(例如,参见这篇文章)。

假设属性是在 Vuex 操作中加载的,流程类似于:

{
  ...
  actions: {
    async comments() {
      try {
        await loadComments()

        EventBus.trigger("comments:load:success")
      } catch (e) {
        EventBus.trigger("comments:load:error", e)
      }
    }
  }
  ...
}

你可以抱怨一下反应性和违背反应性哲学的事件。但这可能是事件更具语义化的一个例子。

2. 反应式方法

我试图将计算排除在我的观点之外。chunkify您可以将其绑定到您的商店,而不是在您的组件内部定义。

所以,假设我有一个名为 JavaScrip 的模块store,它可以导出 Vuex 存储。我将chunkify在该模块中定义为命名函数

function chunkify (a, n) {
   ...
}

(这可以在 JS 模块的底部定义,以提高可读性,这要归功于函数提升。)

然后,在您的商店定义中,

const store = new Vuex.Store({
  state: { ... },
  ...
  getters: {
    chunkedComments (state) {
      return function (chunks) {
        if (state.comments)
          return chunkify(state.comments, chunks);

        return state.comments
      }
    }
  }
  ...
})

在您的组件中,计算的道具现在是

computed: {
  comments() {
    return this.$store.getters.chunkedComments(3);
  },
}

然后更新 cascase 将从中流出getter,它会在comments检索到时更新,这将更新组件的computedprop,这将更新 ui。


推荐阅读