vue中父子组件通过props传递数据,父组件数据ajax异步更新,子组件不动态更新的解决方案
近期在开发中遇到一个问题,把项目中评分星星剥离出来抽象为一个子组件,页面中也用后发现:如果是通过v-for渲染的列表,数据可以正常通过props传递到子组件并渲染加载,但是如果是异步加载获取到的数据能正常传到子组件中,但是不会重新渲染加载。异步加载获得的数据传递给子组件通过v-for渲染的数据传递给子组件查了一些网友的帖子后发现,只要在子组件中加侦听器watch监听props中值的变化,并在值..
用prop传递字符串、数字类型的值一般是没有问题的,不论数据在父组件中是同步获取的还是异步获取的,数据都可以通过prop响应式传递,子组件在监听到父组件值发生变化时会做出相应的改变。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>父子组件传值测试</title>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
</head>
<body>
<div id="app">
<div>{{message}}</div>
<ceshi :str='str' :num='num'></ceshi>
</div>
<script>
Vue.component('ceshi',{
template:`<div>
<div>这是父组件传过来的文本:{{str}}</div>
<div>这是父组件传过来的数字:{{num}}</div>
</div>`,
props:['str','num']
})
var app = new Vue({
el: '#app',
data: {
message: 'Hello Vue!',
str:"父组件上的文本",
num:56
},
created() {
setTimeout(()=>{
this.num = 189
},3000)
}
})
</script>
</body>
</html>
如果传递的数据是数组或对象呢?并且是在异步加载的情况下
<ul>
<li v-for="item in arr01" :key="item">{{item}}</li>
</ul>
arr01:['数组1','数组2','数组3','数组4']
setTimeout(()=>{
this.arr01 = ['数组5','数组6','数组7','数组8']
},3000)
经过验证,同步和异步的数组、对象都可以正常响应式渲染。
接下来我们测试一下包含对象元素的数组可不可以正常响应式渲染。
<ul>
<li v-for="item in arr02" :key="item">饮料{{item.name}}还有{{item.count}}个</li>
</ul>
arr02 = [
{name:'wahah',count:23},
{name:'paise',count:54},
{name:'mengniu',count:36},
{name:'yili',count:44}
]
不管是同步还是异步过来的数组经过v-for渲染都没有问题,并且都可以响应式地渲染。
但是异步方式在使用数组地索引值直接渲染地时候会报undefined地错误,这是因为在DOM渲染地时候数组中还没有数据,却强行读取arr02[1]的属性,当然会报错
<ul>
<li>饮料{{arr02[0].name}}还有{{arr02[0].count}}个</li>
<li>饮料{{arr02[1].name}}还有{{arr02[1].count}}个</li>
<li>饮料{{arr02[2].name}}还有{{arr02[2].count}}个</li>
<li>饮料{{arr02[3].name}}还有{{arr02[3].count}}个</li>
</ul>
data: {
arr02:[]
},
created() {
setTimeout(()=>{
this.arr02 = [
{name:'wahah',count:23},
{name:'paise',count:54},
{name:'mengniu',count:36},
{name:'yili',count:44}
]
},3000)
}
这种报错会在异步数据获取到的时候正常渲染页面,不会有什么大的影响,但是如果异步数据的length长度小于html渲染的数量,也就是根本没有arr02[4]这个数据却渲染了,那么整个页面都不会展示出来。
父组件异步拿到的数据传到子组件还有一点要注意:如果子组件是直接使用父组件传递的数据没有什么问题,但如果子组件使用的是父组件传递过来数据后经过加工的数据(直接加工prop里的数据),那么你父组件数据更新时,子组件的数据是不会响应更新的。
<div>这是父组件传过来的数字:{{num}}</div>
<div>这是copy父组件传过来的数字:{{num02}}</div>
//在子组件中
props:['num'],
data(){
return{
num02:this.num
}
}
//在父组件中
data: {
num:undefined
},
created() {
setTimeout(()=>{
this.num = 189
},3000)
}
结果是3秒过后num的数据更新为189了,但是num02还是原来的undefined,没有更新。(如果是同步数据则没问题)
官方对此的解释是通过props传递数据是单向的。
解决方案
是可以在子组件的computed中监听这种改变:
computed:{
num02(){
return this.num
}
}
这样就解决了不能对父组件异步传的数值进行加工的问题。
如果监听对象被多个数据影响,用computed监听,如果监听数据影响着多个数据,则用watch来监听。
注意:由于对象和数组是引用类型,指向同一个内存空间,所以props是对象和数组时,在子组件内改变是会影响到父组件的。
更多推荐
所有评论(0)