组件关系可分为:父子组件通信,兄弟组件通信,跨级组件通信
自定义事件---子组件给父组件传递数据
使用v-on
除了监听 DOM 事件之外,还可以用于组件之间的自定义事件。
子组件使用 $emit()
来 触发事件,父组件使用 $on()
来监听子组件事件
第一步:自定义事件
第二步:在子组件中使用$emit
触发事件,第一个参数是要触发的事件名,后面的参数是要传递的数据
第三步:在自定义事件中用一个参数来接收
<div id="app">
你的银行卡余额是:{{total}}
<son-component @change='handelTotal'></son-component>
<!-- 自定义的change事件 -->
</div>
<script>
Vue.component('son-component', {
template: `<div>
<button @click='addMoney'> +1000 </button>
<button @click='minusMoney'> -1000 </button>
</div>`,
data: function () {
return {
count: 2000
}
},
methods: {
addMoney() {
this.count = this.count + 1000
this.$emit('change', this.count)
//触发change事件,并传递给它一个参数this.count
},
minusMoney() {
this.count = this.count - 1000
this.$emit('change', this.count)
}
}
})
let app = new Vue({
el: '#app',
data: {
total: 2000
},
methods: {
handelTotal(value) {
//此处的形参value 就是子组件传递过来的数据,即上面的 this.count
this.total = value
}
}
})
</script>
</body>
非父子关系组件之间的通信 --- 父链---子链
有时候两个非父子关系的组件也需要通信,在简单的场景下,可以使用一个空的 vue 实例作为中央事件总线(中介):
let bus = new Vue()
//bus 为自定义名称,非固定写法
//触发组件 a 中的事件:
bus.$emit('a-component',1)
//在组件 b 创建的钩子函数中监听事件
bus.$on('a-component',function(id){
//......
})
从组件a
向组件b
中传递数据,首先要在根组件中定义一个 bus
中介
在a组件中通过 this.$root.bus
拿到根组件中的 bus
中介,再通过this.$root.bus.$emit('lala',this.aaa)
去触发一个事件,并传递一个数据。
然后在 b
组件中,通过钩子函数 created
在a
组件创建的时候就通过this.$root.bus.$on('lala',function(value){})
去监听这个lala
事件
<div id="app">
<a-component></a-component>
<b-component></b-component>
</div>
<script>
Vue.component('a-component', {
template: '<div><button @click="aHandle">点击我向B组件传递数据</button></div>',
data() {
return {
aaa: '我是A的内容'
}
},
methods: {
aHandle() {
//this.$root 表示的是根组件
this.$root.bbb.$emit('lala', this.aaa)
}
}
})
Vue.component('b-component', {
template: '<div>我是B组件</div>',
created() {
//a 组件在创建实例的时候就监听事件--lala事件
this.$root.bbb.$on('lala', function (value) {
alert(value)
})
}
})
let app = new Vue({
el: '#app',
data: {
bbb: new Vue()
}
})
</script>
父链、子链
父链:this.$parent
Vue.component('a-component', {
template: '<button @click="setFatherData">通过点击我修改父组件的数据</button>',
methods: {
setFatherData() {
//拿到父组件中的 msg ,对其进行修改
this.$parent.msg = '数据已经修改了'
}
})
//父链的父链就是 this.$parent.$parent
子链:this.$children
提供了为子组件提供索引的方法,用特殊的属性ref为其增加一个索引
<div id="app">
<a-component ref="a"></a-component>
<b-component ref="b"></b-component>
<c-component ref="c"></c-component>
---{{formChild}}
<button @click="getChildData">我是父组件的按钮,点击我拿到子组件的内容</button>
</div>
<script>
Vue.component('a-component', {
template: '<div>我是a组件</div>',
data() {
return {
msg: '我是a组件的内容'
}
}
})
Vue.component('b-component', {
template: '<div>我是b组件</div>',
data() {
return {
msg: '我是b组件的内容'
}
}
})
Vue.component('c-component', {
template: '<div>我是c组件</div>',
data() {
return {
msg: '我是c组件的内容'
}
}
})
let app = new Vue({
el: '#app',
data: {
formChild: '还未拿到内容'
},
methods: {
getChildData() {
//这个方法用来拿子组件中的内容,但是子组件不止一个
//所以用到 ref 属性为子组件加一个索引
//在需要拿到子组件的内容时直接通过 this.refs.索引名 就可以了
this.formChild = this.$refs.c.msg
}
}
})
</script>