组件的自定义事件
1、一种组件间通信的方式,适用于子组件 ===> 父组件
2、使用场景:A是父组件,B是子组件,B想传递数据给A,那么就要在A中给B绑定自定义事件(事件的回调在A中)
3、绑定自定义事件:
(1)第一种方式,在父组件中:<Demo @atguigu="test" /> 或 <Demo v-on:atguigu="test">
(2)第二种方式,在父组件中:
<Demo ref = "demo" />
....
mounted(){
this.$ref.xxx.$on('atguigu',this.test)
}
(3)若想让自定义事件只能触发一次,可以使用once修饰符,或$once方法。
4、触发自定义事件:this.$emit('atguigu',数据)
5、解绑自定义事件:this.$off('atguigu')
6、组件上也可以绑定原生DOM事件,需要使用native修饰符
7、注意:通过this.$ref.xxx.$on('atguigu',回调)绑定自定义事件时,回调要么在methods中,要么用箭头函数,否则this指向会出问题!!!
Note:回调函数在父组件中
案例一:(props)
1、需求:点击按钮,school能将信息传给父组件。 (使用props进行实现)
2、实现
- App.vue
<template>
<!-- 组件的结构 -->
<div class="title">
<h1>{{msg}}</h1>
<!-- 功能一:通过父组件给子组件传递函数类型的props实现子给付传递数据 -->
<School :getSchoolName="getSchoolName"></School>
</div>
</template>
<script>
import Student from './components/Student'
import School from './components/School'
export default {
name:'App',
components:{
Student,
School
},
data(){
return {
msg:'你好啊!!'
}
},
methods:{
getSchoolName(name){
//console.log('App收到了学校名:',name)
alert('App收到了学校名:'+name)
},
},
}
</script>
<style scoped>
.title{
background: gray;
padding: 5px;
}
</style>
- School.vue
<template>
<!-- 组件的结构 -->
<div class="school">
<h2>学校姓名:{{name}}</h2>
<h2>学校地址:{{address}}</h2>
<button @click="sendSchoolName">点我传递学校名</button>
</div>
</template>
<script>
export default {
name:'School',
data(){
return {
name:'尚硅谷atguigu',
address:'北京',
}
},
props:['getSchoolName'],
methods:{
sendSchoolName(){
this.getSchoolName(this.name)
}
}
}
</script>
<style scoped>
.school{
background: skyblue;
padding: 5px;
}
</style>
3、效果:
案例二:(自定义事件方法一:emit)
1、需求:点击按钮,通过Student组件给App传递学生名字;(使用自定义事件实现)
2、实现:
- App.vue
<template>
<!-- 组件的结构 -->
<div class="title">
<h1>{{msg}}</h1>
<!-- 功能一:通过父组件给子组件传递函数类型的props实现子给付传递数据 -->
<School :getSchoolName="getSchoolName"></School>
<!-- 功能二:通过父组件给 子组件的实例对象vc 绑定一个自定义事件实现子给父传递数据 -->
<Student v-on:atguigu="getStudentName" ></Student>
</div>
</template>
<script>
import Student from './components/Student'
import School from './components/School'
export default {
name:'App',
components:{
Student,
School
},
data(){
return {
msg:'你好啊!!'
}
},
methods:{
getSchoolName(name){
//console.log('App收到了学校名:',name)
alert('App收到了学校名:'+name)
},
getStudentName(name){
alert('App收到了学生名:'+name)
this.name = name
}
},
}
</script>
<style scoped>
.title{
background: gray;
padding: 5px;
}
</style>
- Student.vue
<template>
<!-- 组件的结构 -->
<div class="student">
<h2>学生姓名:{{name}}</h2>
<h2>学生性别:{{sex}}</h2>
<button @click="sendStudentName">点我传递学生名</button>
</div>
</template>
<script>
export default {
name:'Student',
data(){
return {
name:'张三',
sex:'男',
}
},
methods:{
sendStudentName(){
//触发Student实例对象上的点击事件
this.$emit('atguigu',this.name)
}
}
}
</script>
<style scoped>
.student{
background: pink;
padding: 5px;
margin-top: 30px;
}
</style>
3、效果:
案例三:(自定义事件方法三:ref)
1、需求:点击按钮,通过Student组件给App传递学生名字;(使用自定义事件实现)
2、实现:
- App.vue
<template>
<!-- 组件的结构 -->
<div class="title">
<h1>{{msg}}</h1>
<!-- 功能一:通过父组件给子组件传递函数类型的props实现子给付传递数据 -->
<School :getSchoolName="getSchoolName"></School>
<!-- 功能二:通过父组件给 子组件的实例对象vc 绑定一个自定义事件实现子给父传递数据(第一种写法,使用v-on或@) -->
<!-- <Student v-on:atguigu="getStudentName" ></Student> -->
<!-- <Student v-on:atguigu.once="getStudentName" ></Student> --> <!-- 只能点击一次 -->
<!-- 功能二:通过父组件给 子组件的实例对象vc 绑定一个自定义事件实现子给父传递数据(第二种洗发,使用ref)-->
<!-- 这种方法更加灵活,可以在mounted中加setTimeout延迟响应 -->
<Student ref="student"></Student>
</div>
</template>
<script>
import Student from './components/Student'
import School from './components/School'
export default {
name:'App',
components:{
Student,
School
},
data(){
return {
msg:'你好啊!!'
}
},
methods:{
getSchoolName(name){
//console.log('App收到了学校名:',name)
alert('App收到了学校名:'+name)
},
getStudentName(name,...params){ //当接收的参数有很多时,可以用...params接收,接收完毕后params以数组的形式展示
alert('App收到了学生名:'+name+params)
this.name = name
}
},
mounted(){
this.$refs.student.$on('atguigu',this.getStudentName) //绑定自定义事件
// this.$refs.student.$once('atguigu',this.getStudentName) //绑定自定义事件(一次性)
}
}
</script>
<style scoped>
.title{
background: rgb(128, 128, 128);
padding: 5px;
}
</style>
- Student.vue
<template>
<!-- 组件的结构 -->
<div class="student">
<h2>学生姓名:{{name}}</h2>
<h2>学生性别:{{sex}}</h2>
<button @click="sendStudentName">点我传递学生名</button>
</div>
</template>
<script>
export default {
name:'Student',
data(){
return {
name:'张三',
sex:'男',
}
},
methods:{
sendStudentName(){
//触发Student实例对象上的点击事件
this.$emit('atguigu',this.name,123,456,789)
}
}
}
</script>
<style scoped>
.student{
background: pink;
padding: 5px;
margin-top: 30px;
}
</style>
案例四:(解绑一个自定义事件)
1、需求:点击按钮后解绑自定义事件
2、实现:
- Student.vue
<template>
<!-- 组件的结构 -->
<div class="student">
<h2>学生姓名:{{name}}</h2>
<h2>学生性别:{{sex}}</h2>
<button @click="sendStudentName">点我传递学生名</button>
<!-- 解绑自定义事件 -->
<button @click="unbind">解绑atguigu事件</button>
</div>
</template>
<script>
export default {
name:'Student',
data(){
return {
name:'张三',
sex:'男',
}
},
methods:{
sendStudentName(){
//触发Student实例对象上的点击事件
this.$emit('atguigu',this.name,123,456,789)
},
unbind(){
this.$off('atguigu') //只适用于解绑一个自定义事件
}
}
}
</script>
<style scoped>
.student{
background: pink;
padding: 5px;
margin-top: 30px;
}
</style>
案例五:(解绑多个自定义事件)
1、需求:点击按钮后解绑自定义事件
2、实现:
- Student.vue
<template>
<!-- 组件的结构 -->
<div class="student">
<h2>学生姓名:{{name}}</h2>
<h2>学生性别:{{sex}}</h2>
<button @click="sendStudentName">点我传递学生名</button>
<!-- 解绑自定义事件 -->
<button @click="unbind">解绑atguigu事件</button>
</div>
</template>
<script>
export default {
name:'Student',
data(){
return {
name:'张三',
sex:'男',
}
},
methods:{
sendStudentName(){
//触发Student实例对象上的点击事件
this.$emit('atguigu',this.name,123,456,789)
this.$emit('demo')
},
unbind(){
// this.$off('atguigu') //只适用于解绑一个自定义事件
// this.$off() //解绑所有自定义事件
this.$off(['atguigu','demo']) //解绑多个自定义事件
}
}
}
</script>
<style scoped>
.student{
background: pink;
padding: 5px;
margin-top: 30px;
}
</style>
- App.vue
<template>
<!-- 组件的结构 -->
<div class="title">
<h1>{{msg}}</h1>
<!-- 功能一:通过父组件给子组件传递函数类型的props实现子给付传递数据 -->
<School :getSchoolName="getSchoolName"></School>
<!-- 功能二:通过父组件给 子组件的实例对象vc 绑定一个自定义事件实现子给父传递数据(第一种写法,使用v-on或@) -->
<Student v-on:atguigu="getStudentName" v-on:demo="m1"></Student>
<!-- <Student v-on:atguigu.once="getStudentName" ></Student> --> <!-- 只能点击一次 -->
<!-- 功能二:通过父组件给 子组件的实例对象vc 绑定一个自定义事件实现子给父传递数据(第二种洗发,使用ref)-->
<!-- 这种方法更加灵活,可以在mounted中加setTimeout延迟响应 -->
<!-- <Student ref="student"></Student> -->
</div>
</template>
<script>
import Student from './components/Student'
import School from './components/School'
export default {
name:'App',
components:{
Student,
School
},
data(){
return {
msg:'你好啊!!'
}
},
methods:{
getSchoolName(name){
//console.log('App收到了学校名:',name)
alert('App收到了学校名:'+name)
},
getStudentName(name,...params){ //当接收的参数有很多时,可以用...params接收,接收完毕后params以数组的形式展示
alert('App收到了学生名:'+name+params)
this.name = name
},
m1(){
console.log('m1被调用了')
}
},
mounted(){
this.$refs.student.$on('atguigu',this.getStudentName) //绑定自定义事件
// this.$refs.student.$once('atguigu',this.getStudentName) //绑定自定义事件(一次性)
}
}
</script>
<style scoped>
.title{
background: rgb(128, 128, 128);
padding: 5px;
}
</style>