目录
前言: 我们把页面拆分成不同的组件,提高了复用性,但是拆分完组件后,有的数据,在多个组件中都需要使用,但是我们只能在其中一个组件中获取到数据,此时.我们就需要根据组件间的关系来传递数据
1.父传子
核心 子组件中 props 接收 + 父组件中 v-bind 传递数据
1. 父组件中在使用子组件时,利用v-bind把数据传递给子组件
2.子组件中,利用props,接收数据
3.在子组件中使用接收到的数据
props 接收形式 :
1.数组 [ 'params ' ] 直接接收数据
2.对象 { params : type } 对接收到的数据类型进行制定
3.多层对象{ params : type , required : true , default : 1} 对接收到的数据类型,是否必传,默认值进行制定
注意 : props接收到的数据一般不建议更改,如果确实需要更改,在子组件中,声明一个中转属性,把接收到的值作为初始值
代码如下
<div id="app">
<far-component></far-component>
</div>
<template id="far">
<div style="background-color: orange;width: 400px;height: 400px;">
<h1>{{value}}</h1>
<son-component :val="value"></son-component>
</div>
</template>
<template id="son">
<div style="background-color: antiquewhite;width: 200px;height: 200px;">
<h1>子组件收到的数据:{{val}}</h1>
</div>
</template>
<script>
let sonComponent = {
template: '#son',
// props: ['val'],
// props:{
// val:String
// },
props:{
val:{
type:String
required:true,
default:'默认值'
}
}
}
let farComponent = {
template: '#far',
data(){
return {
value:'父组件数据'
}
},
components: {sonComponent}
}
new Vue({
el: '#app',
components: {farComponent}
})
</script>
2.子传父
1. 通过自定义事件实现
通过$emit 和 v-on 实现
1.在父组件中给子组件上通过v-on绑定自定义事件,回调函数在父组件中执行并接收数据
2.在子组件的事件函数中通过$emit()触发自定义事件,并传递参数
代码如下:
<div id="app">
<far-component></far-component>
</div>
<template id="far">
<div>
<h1>父组件:{{message}}</h1>
<hr>
<son-component @demo="getData"></son-component>
</div>
</template>
<template id="son">
<div>
<h1>子组件: {{value}}</h1>
<button @click="sendData">传递数据给父组件</button>
</div>
</template>
<script>
let SonComponent = {
template: '#son',
data() {
return {
value: '子组件中的数据',
}
},
methods:{
sendData(){
this.$emit('demo',this.value)
}
}
}
let FarComponent = {
template: '#far',
components: {SonComponent},
methods:{
getData(params){
this.message = params
}
}
}
new Vue({
el: '#app',
components: {FarComponent}
})
</script>
2.通过ref实现
1. 在父组件中给子组件添加ref属性
2.父组件中一挂载(mounted函数中),利用$refs获取到子组件,利用$on给他绑定自定义事件,事件的回调是methods中的方法
3. 在子组件的事件函数中,触发自定义事件,并传递参
注意: 自定义事件的回调函数中的this不是Vue的实例对象,所以不能在回调函数中直接使用this.传递数据;解决办法: 1. 事件回调写在methods中,然后调用methods中的方法 2. 回调函数使用箭头函数,没有自己的this指向,在当前上下文中的this是Vue的实例对象
代码如下
<div id="app">
<far-component></far-component>
</div>
<template id="far">
<div>
<h1>父组件:{{val}}</h1>
<hr>
<son-component ref="sonCom"></son-component>
</div>
</template>
<template id="son">
<div>
<h1>子组件:</h1>
<button @click="sendData">点击传递数据</button>
</div>
</template>
<script>
let SonComponent = {
template: '#son',
data() {
return {
a: 100,
b: 200
}
},
methods: {
sendData() {
this.$emit('demo', 123)
},
}
}
let FarComponent = {
template: '#far',
components: {SonComponent},
data(){
return {
val:''
}
},
methods: {
getData(a) {
this.val = a
}
},
mounted() {
this.$refs.sonCom.$on('demo', this.getData)
}
}
new Vue({
el: '#app',
components: {FarComponent}
})
</script>
3.父子间通信扩展
$parent 获取父组件
$children 获取所有子组件
$refs 根据ref获取标签对象
$root 获取根组件
代码如下,了解即可
<div id="app">
<far-component></far-component>
</div>
<template id="far">
<div>
<h1>父组件:</h1>
<hr>
<son-component ref="sonCom"></son-component>
<button @click="getCom">点击获取子组件</button>
</div>
</template>
<template id="son">
<div ref="sonCom">
<h1>子组件:</h1>
<button @click="getHtml">点击获取标签</button>
</div>
</template>
<script>
let SonComponent = {
template: '#son',
data(){
return {
a:100,
b:200
}
},
methods:{
sendData(){
console.log('.............')
},
getHtml(){
console.log(this.$refs.sonCom) // 根据ref名称获取标签
console.log(this.$parent) // 获取父组件
console.log(this.$root) // 获取根组件 VM
}
}
}
let FarComponent = {
template: '#far',
components: {SonComponent},
methods:{
getCom(){
console.log(this.$children) // 获取所有子组件
console.log(this.$children[0].a) // 获取某个子组件中的数据
console.log(this.$children[0].b)
console.log(this.$children[0].$refs.sonCom)
}
}
}
new Vue({
el: '#app',
components: {FarComponent}
})
</script>
4.兄弟间通信
实现兄弟间通信的方式常用的有以下两种:
1. 在父子通信的基础上,子组件传递数据给父组件,通过父组件传递给另一个子组件
2. 全局事件总线 globalEventBus
3. 消息订阅与发布(下载第三方库,如pubsub等)
4.1全局事件总线使用
1.安装全局事件总线
new Vue({
el: '#app',
components: {FarComponent,SonComponent},
beforeCreate(){
Vue.prototype.$bus = this
}
})
2. 使用事件总线
1.接收数据
methods: {
getData(a) {
this.val = a
}
},
mounted(){
this.$bus.$on('demo',this.getData)
},
2. 提供数据
methods: {
sendData() {
this.$bus.$emit('demo', this.a)
},
}
全局事件总线实现兄弟通信案例
<div id="app">
<son-component></son-component>
<far-component></far-component>
</div>
<template id="com1">
<div>
<h1>组件1:a: {{a}}; b: {{b}}</h1>
<button @click="sendData">点击发送数据</button>
<hr>
</div>
</template>
<template id="com2">
<div>
<h1>组件2:{{val}}</h1>
</div>
</template>
<script> // 全局事件总线 :
let SonComponent = { //1. 安装全局事件总线 :
template: '#com1', // new Vue({ beforeCreate(){Vue.prototype.$bus = this}})
data() { // 2. 提供数据 : this.$bus.$emit('事件',数据)
return { // 3. 接收数据 : mounted(){this.$bus.$on('事件',回调)}
a: 100,
b: 200
}
},
methods: {
sendData() {
this.$bus.$emit('demo', this.a)
},
}
}
let FarComponent = {
template: '#com2',
data(){
return {
val:''
}
},
methods: {
getData(a) {
console.log(a)
this.val = a
}
},
mounted(){
this.$bus.$on('demo',this.getData)
},
}
new Vue({
el: '#app',
components: {FarComponent,SonComponent},
beforeCreate(){
Vue.prototype.$bus = this
}
})
</script>