当 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>
我试图在 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>