【问题标题】:Make Vue template wait for global object returned by AJAX call使 Vue 模板等待 AJAX 调用返回的全局对象
【发布时间】:2018-10-08 11:02:59
【问题描述】:

我正在尝试在包含按钮、部分、标签等所有文本的字典中等待某些字符串。

我首先将默认字符串列表发送到控制器,该控制器将所有字符串注册到我的 CMS,以防这些特定值不存在。之后,我返回一个包含我的“字典”的新对象,但具有当前语言的正确值。

我使用在window.onload 上触发dispatch() 的事件侦听器运行调用,然后将数据添加到Vuex 模块状态。然后我将它添加到计算的道具中。

computed: {
    cartDictionary() {
        return this.$store.state.dictionaries.myDictionaries['cart']
    }
}

所以现在的问题是:在我的模板中,我尝试从 cartDictionaryprop 获取值,这是一个数组。

<h2 class="checkout-section__header" v-html="cartDictionary['Cart.Heading']"></h2>

但是当组件渲染时,prop 还没有值,因为它正在等待 AJAX 调用完成。所以我当然会收到cannot read property of undefined 错误。

关于如何解决这个问题的任何想法?我希望通过全局对象访问字典,而不是通过 props 传递所有内容,因为它是使用原子设计构建的,而且会非常乏味。

编辑: 添加更多代码以进行澄清。

我的模块:

const dictionaryModule = {
namespaced: true,
state: {
    dictionaries: []
},
mutations: {
    setDictionaries (state, payload) {
        state.dictionaries = payload
    }
},
actions: {
    getDictionaries ({commit}) {
        return new Promise((resolve, reject) => {
            Dictionaries.init().then(response => {
                commit('setDictionaries', response)
                resolve(response)
                })
            })
        }
    }
}

我的商店:

const store = new Vuex.Store({
    modules: {
        cart: cartModule,
        search: searchModule,
        checkout: checkoutModule,
        filter: filterModule,
        product: productModule,
        dictionaries: dictionaryModule
    }
})

window.addEventListener('load', function () {
    store.dispatch('dictionaries/getDictionaries')
})

【问题讨论】:

  • 你能在父子组件中显示你的数据对象吗?
  • @boussadjrabrahim 我所展示的都在同一个组件中,它也是父组件。这是一个混合 Vue/MVC 解决方案,因此“结帐”组件被插入到 Razor 视图中的元素中。
  • 所以请提供我通过 ajax 调用完成的最终对象的结构

标签: vue.js vuex


【解决方案1】:

我也希望看到更多您的代码,但由于我无法评论您的问题(您需要 rep > 50),所以就这样...

我有两个一般性建议:

  • 您是否正确设置了操作?突变总是同步的,而动作允许异步操作。因此,如果您的 http 客户端返回了一个承诺(例如,axios 确实如此),您应该在调用相应的突变之前等待您的操作中的结果。本章见官方 vuex-docs:https://vuex.vuejs.org/guide/actions.html

  • 您不应该使用诸如 window.onload 之类的东西,而应使用 Vue.js 提供的钩子。检查这个:https://vuejs.org/v2/guide/instance.html#Lifecycle-Diagram

  • 编辑:作为第三个建议:检查是否正确调用了动作和突变。如果它们在自己的模块中处理,则必须将模块注册到状态。

【讨论】:

  • 我认为我的模块设置方式不是问题。 const dictionaryModule = { namespaced: true, state: { dictionaries: [] }, mutations: { setDictionaries (state, payload) { state.dictionaries = payload } }, actions: { getDictionaries ({commit}) { return new Promise((resolve, reject) => { Dictionaries.init().then(response => { commit('setDictionaries', response) resolve(response) }) }) } } }
  • @Atombob 你应该用那个 sn-p 更新你的问题,使其更具可读性
  • 正在调用操作并返回数据,这不是问题。只是在渲染数组的时候是未定义的
  • 我显然应该在提供答案之前等待更多细节......状态,突变和动作看起来很好。此外,您提供了一个初始状态...如果您的状态内一切正常,则可能与您调度操作的方式有关。您不能在您的顶级组件的 created-hook 中调度“dictionaries/getDictionaries”操作吗?
  • 是的,但问题是我没有顶级组件。我有一堆不共享共同父级的组件。这就是为什么我希望从一个地方进行调用而不是在每个组件中进行调用:)
【解决方案2】:

我认为您可以观看 cartDictionary 并设置另一个数据变量。

喜欢这个

<h2 class="checkout-section__header" v-html="cartHeading"></h2>



data () {
    return {
      cartHeading: ''
    }
},
watch: {
  'cartDictionary': function (after, before) {
    if (after) {
      this.cartHeading = after
    }
  }
}

因为this.$store.state.dictionaries.myDictionarie一开始是未定义的,所以vuejs无法映射myDictionarie['core']。这就是您的代码不起作用的原因。

你也可以这样做

state: {
    dictionaries: {
        myDictionaries: {}
    }
}

并在解析期间设置dictionaries 键值。

【讨论】:

  • 对,但我希望尽可能避免制作“空”道具。这甚至可能吗?
  • 你可以试试这个cartDictionary() { const myDictionaries = this.$store.state.dictionaries.myDictionaries return myDictionaries &amp;&amp; myDictionaries['cart'] || [] } 抱歉格式化。 :(
  • 好消息是它起作用了。坏消息是我不明白刚刚发生了什么哈哈。这甚至是如何工作的?
  • 编辑了答案。希望对您有所帮助。
猜你喜欢
  • 2011-11-15
  • 1970-01-01
  • 1970-01-01
  • 2011-12-17
  • 1970-01-01
  • 2020-09-11
  • 1970-01-01
  • 1970-01-01
  • 2021-03-18
相关资源
最近更新 更多