父子组件的通信方式
(1)父 -> 子:props (在父组件中通过v-bind绑定,子组件用props接收)
<div id="app">
<!-- 将父组件的数据绑定到子组件上使用 v-bind -->
<soncnp v-bind:cmsg="msg" :cmovies="movies"></soncnp>
</div>
<template id="son">
<div>
<h1>这是子组件,使用父组件的数据</h1>
<h2>{{cmsg}}</h2>
<ul>
<li v-for="itme in cmovies">{{itme}}</li>
</ul>
</div>
</template>
<script type="text/javascript">
let sonCnp={
template:'#son',
//在子组件中接props收数据并使用
//数组中存放的是父组件,自定义的属性名
// props:['cmsg',"cmovies"],//数组写法
props:{//对象写法
cmsg:String,//限制为String类型
cmovies:Array,//限制为数组类型
//提供默认值
cmsg:{
type:String,
//default 当没有传递父组件的变量的时候会显示的内容、
default:'没有传递数据',
required:true//必须传值
}
},
}
let vm=new Vue({
el:'#app',
data:{
msg:'父组件向子组件传递数据',
movies:["八百","赤狐书生","信条","花木兰"]
// msg:1,
// movies:1
},
components:{
"soncnp":sonCnp
}
})
</script>
props除了数组,也可以是一个对象,此时对象的键对应的props的名称,值为是一个对象时,可以包含如下属性:
(1)type类型,可以设置为:String、Number、Boolean、Array、Object、Date等等;
如果只设置type而未设置其他选项,则值可以直接用类型,例如:props:{title:Object}
(2) default ;默认值
(3)required ;布尔类型,表示是否必填项目
(4) validator ;自定义验证函数
扩展:propsData
它不是和属性有关的,它用在全局扩展时进行传递数据的--------只能在new的时候传递
首先这个使用率不高,因为后期会有vuex(状态管理),它的作用是单页应用中保持状态的。
<body>
<div id="app">
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script type="text/javascript">
//通过extend拓展一个新的组件
var fatheriswho=Vue.extend({
//传递数据
template:`
<p>问题:{{question}} 回答:{{eg}}</p>
`,
data(){
return{
question:'支付宝他爹是谁?'
}
},
//需要通过prop进行数据传递
//注意接收的变量名要和propsData的变量名一致,不然拿不到值
props:['eg']
})
//实例化对象
new fatheriswho({propsData:{'eg':'马云'}}).$mount('#app')
</script>
</body>
(2)父 -> 子:ref
<1> ref用在普通的dom元素上,引用指向dom元素,通过$refs可以获取到改dom的属性集合,作用与js选择器类似
<2> $refs只能进行获取组件的实例对象,不能直接传值,强行传会报错
<div id="app">
<!-- 使用子组件 -->
<my-son ref="xg"></my-son>
<button type="button" @click="changs">获取组件的内容</button>
</div>
<template id="son">
<div id="">
<h2>这是子组件</h2>
<div style="width: 200px; border: 1px solid plum;">
{{cmsg}}
</div>
<button type="button" @click="chang">修改</button>
</div>
</template>
<script type="text/javascript">
// 子组件选项对象
let MySon ={
template:'#son',
props:{
cmsg:Number,//限定类型
},
data(){
return {
aaa: '我是aaa'
}
},
methods:{
getcmsg(){
this.aaa='ddd';
}
}
}
// 以Vue实例作为父组件
new Vue({
el:'#app',
data:{
msg:'这个是父组件中的msg'
},
methods:{
changs(){
// 获取的是xg组件实例
console.log(this.$refs.xg)
console.log(this.$refs.xg.aaa) // 我是aaa // 获取子组件的aaa属性
}
},
components:{
// 注册子组件
MySon
}
})
</script>
注意:ref和props的区别
(1)(父->子)props着重传递数据,但是不能调用子组件的属性和方法
(2)(父->子)ref着重与引用,主要用于调用子组件中的属性和方法,不能传递数据,如果强行传递,
会报错。
(3)子 -> 父:监听发射自定义事件 $emit
①子组件用 $emit 向父组件发射事件名称--------- $emit(“自定义事件名”, 数据)
②父组件用 v-on或 $on 监听子组件的事件------------------ v-on:自定义事件名=“方法"
<div id="app">
<h1>我是父组件{{fMsg}}</h1>
<!-- 使用子组件 -->
<!-- v-on接收子组件传递的数据 biu为事件名,与子组件一致 -->
<my-son v-on:biu="show"></my-son>
</div>
<template id="sontem">
<div style="border: 2px solid red">
<h3>我是子组件</h3>
<button type="button" @click="sonTofather">向父组件传递数据</button>
</div>
</template>
<script>
let vm = new Vue({
el:'#app',
data:{
fMsg:null
},
methods:{
show(data){
this.fMsg = data
}
},
components:{
// 创建子组件
'my-son':{
template:'#sontem',
data(){
return {
sMsg:{
id:111,
name:"小菲"
}
}
},
methods:{
sonTofather(){
this.$emit('biu', this.sMsg)
}
}
}
}
})
</script>
(4)非父子组件通讯--------(非直系亲属传值):eventBus
如果项目不大,我们不用 vuex 来解决非父子组件之间的传值,而是直接通过(事件车)
事件车:可以用来结果平级组件(兄弟组件)、跨级组件之间的通讯(祖孙组件)
事件车的实现:利用一个公共的Vue实例,发射 (
e
m
i
t
)
和
监
听
(
emit) 和监听 (
emit)和监听(on) 来达到不是父子组件的通讯
①首先,创建一共公共Vue实例
②接着,在需要的地方引入
③最后,接收
eventBus相当于一个转接器,一个组件向其发送数据,另一个组件可接收数据