组件之间的数据通讯需要通过参数传递,父组件传递给子组件通过props属性,结合属性的动态绑定实现。props中有相应的属性和父组件中要传递的属性对应,相当于中间桥梁。
子组件无法直接引用父组件中的数据。
若不通过props传递,直接引用父组件的数据,会报错,如下:
<div id="app">
<mycpn></mycpn>
</div>
<script src="../js/vue.js"></script>
<template id="cpn">
<div>
<h2>{{message}}</h2>
</div>
</template>
<script>
//mycpn相当于vue中的子组件
const mycpn={
template:'#cpn'
}
//创建并注册组件
Vue.component('mycpn',mycpn);
//vue相当于父组件
const vue = new Vue({
el:"#app",
data:{
message:"hello vue!"
},
components:{
mycpn:mycpn
}
});
</script>
运行后提示message未定义,效果如下:
通过props属性传递,并通过v-bind动态绑定后,如下:
<div id="app">
<mycpn :cmessage="message"></mycpn>
</div>
<script src="../js/vue.js"></script>
<template id="cpn">
<div>
<h2>{{cmessage}}</h2>
</div>
</template>
<script>
const mycpn={
template:'#cpn',
props:{
cmessage:{
type:String,
required:true,
default:'hello'
}
}
}
//创建并注册组件
Vue.component('mycpn',mycpn);
const vue = new Vue({
el:"#app",
data:{
message:"hello vue!"
},
components:{
mycpn:mycpn
}
});
</script>
注意props的写法,可以写成数组props:[],也可以写成对象props:{},对象比较常用。
cmessage:{
type:String,
required:true,
default:'hello'
}
type表示数据类型;required表示该属性是必须的,如果没有动态绑定该属性,会报错;default是默认值。
如果type为数组或者对象类型,default的写法上会有所不同,必须以函数的形式返回。
运行效果如下:
required:true,如果没有动态绑定cmessage属性,将<mycpn :cmessage="message"></mycpn>改写成<mycpn></mycpn>,会显示默认值,并且会报错。效果如下:
子组件的属性必须通过动态绑定v-bind的形式,简写为:,如果不通过动态绑定,而是直接添加属性<mycpn cmessage="message"></mycpn>,该属性将被解析成字符串,而不会到父组件中解析相关属性。如下所示:
如果被传递的数据是对象类型或者数组类型,default的写法会有变化,否则会报错,如下所示:
<div id="app">
<mycpn :cmessage="message" ></mycpn>
</div>
<script src="../js/vue.js"></script>
<template id="cpn">
<div>
<h2>{{cmessage}}</h2>
<p>{{cfruits}}</p>
</div>
</template>
<script>
const mycpn={
template:'#cpn',
props:{
cmessage:{
type:String,
required:true,
default:'hello'
},
cfruits:{
type:Array,
default:['苹果']
}
}
}
//创建并注册组件
Vue.component('mycpn',mycpn);
const vue = new Vue({
el:"#app",
data:{
message:"hello vue!",
fruits:['苹果','香蕉','菠萝']
},
components:{
mycpn:mycpn
}
});
</script>
当显示默认值的时候会报错,cfruits的默认值必须以工场函数的形式返回。如下所示:
修改如下:
<div id="app">
<mycpn :cmessage="message" :cfruits="fruits"></mycpn>
</div>
<script src="../js/vue.js"></script>
<template id="cpn">
<div>
<h2>{{cmessage}}</h2>
<ul>
<li v-for="(item,index) in cfruits">{{item}}</li>
</ul>
</div>
</template>
<script>
//mycpn相当于vue中的子组件
const mycpn={
template:'#cpn',
props:{
cmessage:{
type:String,
required:true,
default:'hello'
},
cfruits:{
type:Array,
default(){
return ['苹果']
}
}
}
}
//创建并注册组件
Vue.component('mycpn',mycpn);
//vue相当于父组件
const vue = new Vue({
el:"#app",
data:{
message:"hello vue!",
fruits:['苹果','香蕉','菠萝']
},
components:{
mycpn:mycpn
}
});
</script>
运行效果如下: