用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是对象和数组时,在子组件内改变是会影响到父组件的。

 

 

 

 

 

Logo

前往低代码交流专区

更多推荐