组件的自定义事件(绑定、解绑)

温馨提示:总结在最下方,如若不想看代码,请滚动至最下方查看相关知识点,谢谢!
App.vue

<template>
   <div class="app">
      <h1>学生姓名是:{{studentName}}</h1>
      //通过父组件给子组件传递函数类型的props实现:子给父传递数据
      <School :getSchoolName="getSchoolName"/>
      //通过父组件给子组件绑定一个自定义事件实现:子给父传递数据
      //第一种写法(使用@) @xxx.once:表示只执行一次
      <Student @xxx="getStudentName"/><Student @xxx.once="getStudentName"/>
      //第一种写法(使用v-on)
      <Student v-on:xxx="getStudentName"/>
	  //通过父组件给子组件绑定一个自定义事件实现:子给父传递数据
	  //第二种写法(使用ref,灵活性更强,例如:等3s后执行,第一种方法无法实现,第二种方法则可以)
      <Student ref="student"/>
      
      //绑定原生dom事件第一种写法:需在对应组件内配合this.$emit()方法使用
      <Student ref="student" @click="show"/>
      //绑定原生dom事件第二种写法:如下使用native修饰符,
      //随即将click事件交给了Student组件中最外层的div即可生效
      <Student ref="student" @click.native="show"/>
      //绑定多个自定义事件   @xxx,@aaa是自定义事件名;getStudentName,m1是回调名
      <Student @xxx="getStudentName" @aaa="m1"/>
   </div>
</template>

<script>
import School from './components/School'
import Student from './components/School'
export default {
	name:'App',
	components: {
	   School,
	   Student
	}
	data() {
	   studentName: '',
	},
	methods: {
	   getSchoolName(name) {
	      console.log('App收到了School学校名',name)
	   },
	   getStudentName(name) {
	      console.log('App收到了Student学生名',name)
	   },
	   //接收多个参数
	   //第一种:直接接收
	   getStudentName(name,x,y,z) {
	      console.log('App收到了Student学生名',name,x,y,z)
	   },
	   //第二种:使用es6的写法:name当作形参接收,...params当作数组接收
	   getStudentName(name,...params) {
	      console.log('App收到了Student学生名',name,params)
	      //总结中的第7点注意点
	      //通过this.$refs.demo.$on('xxx',回调)绑定自定义事件时,回调要配置在methods中
	      this.studentName = name
	   },
	   //绑定第二个自定义事件
	   m1() {
	     console.log('aaa事件被触发了~')
	   }
	},
	mounted() {
	   //等3s后执行,如若没有这种需求,则可以采用第一种方式使用@/v-on方式绑定自定义事件
	   setTimeout(() => {
	      this.$refs.student.$on('xxx',this.getStudentName)
	   },3000)

	   //无上述(等3s后执行)需求则第二种方法的正常写法如下:
	   //总结中的第7点注意点
	   //通过this.$refs.demo.$on('xxx',回调)绑定自定义事件时,
	   //this.getStudentName需要在methods中配置
	   this.$refs.student.$on('xxx',this.getStudentName)
       //或者不在methods中配置this.getStudentName
       //使用一般函数:
	   this.$refs.student.$on('xxx',function(name,...params){
	      console.log('App收到了Student学生名',name,params)
	      //此时的this指向的是student组件实例并不是App组件
	      //所以this.studentName = name 并不会作用在App上,
	      //App上的studentName并无数据,无法呈现于页面
	      console.log(this)
	      this.studentName = name
	   })
	   //使用箭头函数:
	   //因为箭头函数没有属于自己的this所以向外找到了mounted()函数,
	   //mounted()函数属于当前组件App,所以找到的this就是指向app的组件实例对象
	   this.$refs.student.$on('xxx',(name,...params)=>{
	      console.log('App收到了Student学生名',name,params)
	      //此时的this指向的是App组件
	      //所以this.studentName = name 作用于app,
	      //App上的studentName有了数据,随即呈现于页面
	      console.log(this)
	      this.studentName = name
	   })
	   //使用once表示只执行一次
	   this.$refs.student.$once('xxx',this.getStudentName)
	}
}
</script>

<style scoped>
.app {
    background-colo: gray;
}
</style>

School.vue

<template>
   <div class="school">
      <h2>学校名称:{{ name }}</h2>
      <h2>学校地址:{{ address }}</h2>
      <button @click="sendSchoolName">把学校名给App</button>
   </div>
</template>

<script>
export default {
	name:'School',
	props: ['getSchoolName']
	data() {
	   name: '清华大学',
	   address: '北京',
	},
	methods: {
	   sendSchoolName() {
	       this.getSchoolName(this.name)
	   }
	}
}
</script>

<style scoped>
.school {
  background-colo: blue;
}
</style>

Student.vue

<template>
   <div class="student">
      <h2>学生名称:{{ name }}</h2>
      <h2>学生年龄:{{ age }}</h2>
      <h2>当前number的和为:{{ number }}</h2>
      <button @click="add">点我number++</button>
      <button @click="sendStudentName">把学生名给App</button>
      //解绑自定义事件
      <button @click="unbind">把学生名给App</button>
      //销毁实例(vc)
      <button @click="death">销毁当前Student组件的实例(vc)</button>
   </div>
</template>

<script>
export default {
	name:'Student',
	data() {
	   name: '陈慕夏',
	   age: 18,
	   number: 0,
	},
	methods: {
	   add() {
	      console.log('add回调被调用了!')
	      this.number++
	   },
	   sendStudentName() {
	       //触发Student组件实例身上的xxx自定义事件
	       this.$emit('xxx',this.name)
	       //当传递的参数较多时,有2种处理方法如下:
	       //第一种:将多个参数包装成对象传递
	       this.$emit('xxx',this.name,{666,888,999})
	       //第二种:如下直接传递
	       this.$emit('xxx',this.name,666,888,999)

          //绑定第二个自定义事件  使用自定义事件名xxx,aaa,不是回调名!!!
          this.$emit('aaa')

         //想要触发组件上的原生dom事件,需要和自定义事件一样使用this.$emit()
         //原因:所有绑定在组件上的事件,都会被看作是自定义事件,如若需要出发则需要使用this.$emit()
         this.$emit('click')
	   },
	   unbind() {
	      //解绑一个自定义事件
	      this.$off('xxx') 
	      //解绑多个自定义事件
	      this.$off(['xxx','aaa']) 
	      //解绑所有的自定义事件
	      this.$off()
	   },
	   death() {
	      //销毁了当前Student组件的实例(vc)
	      //销毁后所有Student组件的实例的自定义事件全都失效了
	      //此时的add还是可以执行的,但数据响应已经失效。原因是因为add是原生的dom事件,
	      this.$destroy()
	   }
	}
}
</script>

<style scoped>
.student {
  background-colo: red;
}
</style>

main.js

//引入Vue
import Vue from 'vue'
//引入App
import App from './App.vue'
//关闭Vue的生产提示
Vue.config.productionTip = false

//创建vm
new Vue({
   el: '#app',
   render: h => h(App),
   //销毁vm
   mounted() {
      setTimeout(()=>{
          //此处this指向vm
          //3s后vm被销毁,则所有组件里的自定义事件也被销毁了
          this.$destroy()
      },3000)
   }
})

总结:
1. 一种组件间通信的方式,适用于:子组件 ===> 父组件
2. 使用场景:A是父组件,B是子组件,B想给A传数据,那么就要在A中给B绑定自定义事件【事件的回调在A中】
3. 绑定自定义事件:
(1). 第一种方式:在父组件中:<Demo @xxx="test" /> 或 <Demo v-on:xxx="test" />
(2). 第二种方式:在父组件中
<Demo ref="demo" />
........
mounted() {
this.$refs.demo.$on('xxx',this.test)
}
(3). 若想让自定义事件只能触发一次,可以用once修饰符,或$once方法
4. 触发自定义事件:this.$emit('xxx',数据)
5. 解绑自定义事件:this.$offf(''xxx)
6. 组件上也可以绑定原生DOM事件,需要使用native修饰符
7. 注意:通过this.$refs.demo.$on('xxx',回调)绑定自定义事件时,回调要么配置在methods,要么用箭头函数,否则this指向会出问题!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值