【问题标题】:Loop out async data in vue component循环出Vue组件中的异步数据
【发布时间】:2018-11-23 05:21:44
【问题描述】:

我需要加载异步数据,然后将其循环到 vue 组件中。我知道循环在我有数据之前运行,但我不知道如何重新运行或保持循环,直到我有数据。我测试过但不起作用的一种解决方案是 Data 中的加载属性和 isLoaded 计算函数,然后 -

                <div v-if="isLoaded">
                    <ul v-for="item in menu.items">
                        <li>{{ item.heading }}</li>
                    </ul>
                </div>

似乎循环仍然运行,我得到了错误 -

TypeError: Cannot read property 'items' of undefined

整个页面似乎在该错误之后冻结,所以我可能无法在异步函数中将加载的 Data 属性设置为 true。我已经测试过在创建和挂载的钩子中运行异步。

当我离开页面并返回时,一切正常,可能是因为数据已加载。我还测试了通过单击按钮来设置 loded 属性,当循环没有注释而不是循环运行时它工作正常。

我认为这是谷歌搜索后的常见解决方案,但我无法让它工作。有什么问题或任何其他建议(我的最后一个是在其他页面中加载数据)。

另见-

export default {
    data() {
        return {
            loaded: false,

和-

computed: {
    isLoaded() {

        return this.loaded

    }

【问题讨论】:

    标签: vue.js


    【解决方案1】:

    您可以简单地检查menu 不是undefined

    <div v-if="menu && menu.items">
        <ul v-for="item in menu.items">
           <li>{{ item.heading }}</li>
        </ul>
     </div>
    

    或在您获取数据的位置:

    methods: {
      getData() {
        this.loaded = false
        callApi().then(res => {
          this.menu = res // example
          this.loaded = true
        })
      }
    }
    
     <div v-if="loaded">
       <ul v-for="item in menu.items">
         <li>{{ item.heading }}</li>
       </ul>
     </div>
    

    【讨论】:

    • 感谢您的回答。在您的第一个示例中,错误消失了,但循环永远不会再次运行(加载数据时),这很奇怪。第二个例子和我做的很像,只是我在创建或挂载的钩子中做。
    • 你可以使用 vue-devtools 检查menu 变量的值吗?
    • 它未定义。所以这可能是我的问题,而不是异步和加载部分。上面的狮身人面像也有一个好点,我会在那里发表评论。
    【解决方案2】:

    你可能遇到的问题:

    1. menu is null编译模板时,如@ittus已经回答,使用v-if控制流程。

    2. 在向一个对象添加属性时使用Vue API: $set。 (查看Vue: Reactivity in Depth了解更多详情)

    所以代码会像下面的演示:

    Vue.config.productionTip = false
    app = new Vue({
      el: "#app",
      data: {
        menu: null,
        loading: false
      },
      mounted: function () {
        this.loading = true
        setTimeout(() => {
          this.menu = this.menu ? this.menu : {}
          this.$set(this.menu, 'items', [{'heading': 'a1'},{'heading': 'b1'}, {'heading': 'c1'}])
          this.loading = false
        }, 1500)
      }
    })
    <script src="https://unpkg.com/vue@2.5.16/dist/vue.js"></script>
    <div id="app">
        <div v-if="!loading">
          <div v-if="menu">
            <ul v-for="item in menu.items">
                <li>{{ item.heading }}</li>
            </ul>
          </div>
          <p v-else>No Data</p>
        </div>
        <p v-else>Loading...</p>
    </div>

    【讨论】:

    • 所以这可能是我的问题。我需要使用 $set。但是我尝试复制的对象(菜单)来自 Firebase,似乎即使我在回调中调用 getter(然后)我仍然要快。如果我在您的计时器中执行此操作,则一切正常,只是我需要给它一个名称(属性),因此它将是循环中的 menu.menu.items。
    • 至少我认为我使用了一个承诺。我正在使用 vuexfire,我不认为这是一个承诺,所以现在我需要弄清楚。这嘘……现在对我来说太难了:(
    • @user2856066,不知道你的意思,如果vuexfire引起了问题,你可以将它添加到这个问题或发布另一个问题。对于你提到的menu.menu.items,可能你想使用this.$set(this.$data, 'menu', newMenuItems)
    • 非常感谢,它的工作。我有几个错误和我不知道的事情。正在加载,如何使用 $set 以及来自商店的回调/承诺错误。
    猜你喜欢
    • 2018-09-18
    • 2020-03-07
    • 1970-01-01
    • 1970-01-01
    • 2018-10-17
    • 1970-01-01
    • 2017-07-24
    • 1970-01-01
    • 2017-05-16
    相关资源
    最近更新 更多