温馨提示:总结在最下方,如若不想看代码,请滚动至最下方查看相关知识点,谢谢!
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指向会出问题!