Vue2--Vue脚手架组件自定义事件

123 阅读1分钟

组件的自定义事件

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、效果:

image.png

image.png

案例二:(自定义事件方法一: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、效果:

image.png

image.png

案例三:(自定义事件方法三: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>

注意:也可以用生命周期中的destory钩子进行销毁,例如:this.$destory()。销毁后所有Student实例的自定义对象均不奏效