当 parent 中的数据在 Vue.js 中发生变化时如何 re-render 内部组件

How to re-render inner component when data from parent changes in Vue.js

我试图在 parent 组件中更新某些值时从 API 获取一些数据,然后在 child 组件中使用它。我尝试了几件事,但 none 成功了。

这是我的组件的简化版本:

Parent

<template lang="html">
<div id="wrapper">
    <h4>My Super Component</h4>
    <button v-on:click="setListID">Load another list</button>
    <ChildComponent :usernames="usernames"></ChildComponent>
</div>
</template>

<script>
import ChildComponent from "./ChildComponent.vue"

export default {
    components: {
        ChildComponent
    },
    data() {
        return {
            listID: 0,
            usernames: undefined,
        }
    },
    watch: {
        listID: function(newID) {
            this.usernames = getUsernames(newID)
        }
    },
    methods: {
        setListID() {
            let id = +prompt("Input the list ID");
            if (Number.isNaN(id)) {
                alert("Please input a valid number");
            } else {
                this.listID = id;
            }
        }
    },
    async mounted() {
        this.usernames = await getUsernames(this.listID)
    }
}

function sleep(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
}

// Simulating an API call
async function getUsernames(listID) {
    sleep(200).then(() => {
        switch (listID) {
            case 0:
                return ['Pierre', 'Paul', 'Jaques']
            case 1:
                return ['Riri', 'Fifi', 'Loulou']
            case 2:
                return ['Alex', 'Sam', 'Clover']
            default:
                return []
        }
    })
}
</script>

Child

<template lang="html">
    <p v-for="username in usernames">{{username}}</p>
</template>

<script>
export default {
    props: {
        usernames: Object
    },
}
</script>

我在 child 中得到的道具是一个 Promise,我试图传递一个数组,但由于获取数据的函数是异步的,我不能等待手表,我有点卡住了。

更新:

我认为问题来自这段代码:

// Simulating an API call
async function getUsernames(listID) {
    await sleep(200).then(() => {
        switch (listID) {
            case 0:
                return ['Pierre', 'Paul', 'Jaques']
            case 1:
                return ['Riri', 'Fifi', 'Loulou']
            case 2:
                return ['Alex', 'Sam', 'Clover']
            default:
                return []
        }
    })
    return 'returned too early'
}

函数总是returns 'returned too early'。当我删除此默认值 return 时,undefined 被 return 编辑并且我的 child 组件将其用作数组。

您发送数组的道具似乎有问题,但在您期望对象的子组件中。 试试下面的代码看看

<template lang="HTML">
  <p v-for="(username, index) in usernames" :key="index">{{username}}</p>

</template>

<script>
export default {
    props: {
        type: Object, // or Aarray
        default: () => {
          return {} // [] if the type is array
        }
    },
}
</script>

像下面的片段一样尝试

Vue.component('Child', {
  template: `
    <div class="">
      <p v-for="username in usernames">{{username}}</p>
    </div>
  `,
  props: {
    usernames: Array
  },
})

new Vue({
  el: '#demo',
  data() {
    return {
      listID: 0,
      usernames: undefined,
    }
  },
  watch: {
    listID: async function(newID) {
      this.usernames = await this.getUsernames(newID)
    }
  },
  methods: {
    setListID() {
      let id = +prompt("Input the list ID");
      if (Number.isNaN(id)) {
        alert("Please input a valid number");
      } else {
        this.listID = Number(id);
      }
    },
    sleep(ms) {
      return new Promise(resolve => setTimeout(resolve, ms));
    },
    getUsernames(listID) {
      return this.sleep(200).then(() => {
        switch (listID) {
            case 0:
                return ['Pierre', 'Paul', 'Jaques']
            case 1:
                return ['Riri', 'Fifi', 'Loulou']
            case 2:
                return ['Alex', 'Sam', 'Clover']
            default:
                return []
        }
      })
    }
  },
  async mounted() {
    this.usernames = await this.getUsernames(this.listID)
  }
})

Vue.config.productionTip = false
Vue.config.devtools = false
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="demo">
<div id="wrapper">
    <h4>My Super Component</h4>
    <button v-on:click="setListID">Load another list</button>
    <Child :usernames="usernames"></ChildComponent>
</div>
</div>