【问题标题】:Sequential dependent functions in Vuex actionVuex动作中的顺序依赖函数
【发布时间】:2020-11-14 07:18:14
【问题描述】:

我目前正在构建一个使用来自 Contentful API 的数据的 Vue 应用程序。对于每个条目,我都有一个 thumbnail(图像)字段,我想从中提取突出的颜色作为十六进制值,并将它们存储在状态中以便在应用程序的其他地方使用。

使用 Vuex 操作 (getAllProjects) 查询 API,运行 Vibrant (node-vibrant) 并将响应提交到状态。

async getAllProjects({ commit }) {
    let {
      fields: { order: order }
    } = await api.getEntry("entry");
    let projects = order;

    projects.forEach(p =>
      Vibrant.from(`https:${p.fields.thumbnail.fields.file.url}`)
        .getPalette()
        .then(palette => (p.fields.accent = palette.Vibrant.hex))
    );

    console.log(projects);

    // Commit to state
    commit("setAllProjects", projects);
  }

当我在调用commmit 之前记录projects 的内容时,我可以看到在accent 键下添加了 之后的十六进制值。但是,当我在 devtools 中检查突变有效负载时,accent 键丢失了,因此不会处于该状态。

我如何构建这些任务,以便commit 仅在 API 调用和 Vibrant 依次运行之后触发?

【问题讨论】:

  • 你确定在项目中发现了口音吗? forEach() 方法不会改变它开始操作的数组。
  • @crosen9999 API 响应中不存在accent 键,我正在尝试添加该键并将其值分配为Vibrant.getPalette() 的输出,然后提交修改后的数组(包括原始响应值加上新的accent 键)到状态。 编辑:accent 字段不是内容模型的一部分,所以当我说密钥不是 API 响应的一部分时,这种行为是预期的。
  • 我的意思是代码似乎不会将属性添加到项目中,因为 forEach 不会修改项目;它修改每个元素的副本。请在下面尝试我的答案,看看是否有效。
  • 我不太了解 Vibrant,对我来说这似乎是循环回调的时间问题,据我所知,您可以选择使用 Promise。在这种情况下,有很多选择,但要测试它,您可以在每个 .then() 调用中提交,并用新数据覆盖直到结束(这太可怕了)但如果它有效,我们可以找到一个好的解决方案等待进程。

标签: javascript vue.js vuex contentful


【解决方案1】:

您不能在 Vue 中为对象添加属性并使其具有反应性;你必须使用 Vue.set 方法。

请尝试将 forEach 块替换为以下内容,这会使用 Vue.set 添加新属性:

    for (i=0; i<projects.length; i++)
      Vibrant.from(`https:${projects[i].fields.thumbnail.fields.file.url}`)
        .getPalette()
        .then(palette => (Vue.set(projects[i].fields, accent, palette.Vibrant.hex)))
    );

更新:在这种情况下,将格式从 forEach 更改为传统的 for 循环可能是无偿的,因为所做的分配是针对项目的对象属性而不是原语。

【讨论】:

  • X.forEach((e, i) => { ... });用于相同的目的,只有 forEach 必须比旧的 for 循环更具可读性。
  • “forEach() 不会改变调用它的数组。”。请看developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
  • for() 也没有,您正在使用索引来改变初始订单的值,您可以通过使用索引参数来实现与 forEach() 相同的效果。你可以使用 map() 来做同样的事情,它实际上返回一个数组(不要这样做),但你可以。
  • const foo = [ 1, 2, 3 ]; foo.forEach((e, i) => { foo[i]++; });控制台.log(foo);工作正常,这不是他的问题。
  • 但是他没有像你那样使用索引;他正在使用来自 forEach 的 p 参数,这不会改变项目。他可以选择在保留 forEach 的同时使用索引,但目前他没有这样做。
【解决方案2】:

我没有在 StackOverflow 上花费太多时间,如果上述答案有效,我真的为你感到高兴。

但我希望从该答案中您会收到控制台警告,告诉您不要直接改变状态。

现在发生这种情况是因为 Vue.set() 实际上确实帮助 Vue 响应性地理解发生了变化,可能深深地嵌套在对象中。

这里的问题是,由于您正在循环对象,并且一直在更改它,因此提交(Mutator 调用)不是一个更改状态 - Vue.set() 实际上是在每次迭代时更改它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-09-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-30
    • 2017-01-07
    • 2015-11-22
    相关资源
    最近更新 更多