文章目录
1 Vue子组件向父组件传递数据
1.1 知识点: 组件的自定义事件
-
一种组件间通信的方式,适用于:子组件 ===> 父组件
-
使用场景:A是父组件,B是子组件,B想给A传数据,那么就要在A中给B绑定自定义事件(事件的回调在A中)。
-
绑定自定义事件:
-
第一种方式,在父组件中:
<Demo @atguigu="test"/>
或<Demo v-on:atguigu="test"/>
-
第二种方式,在父组件中:
<Demo ref="demo"/> ...... mounted(){ this.$refs.xxx.$on('atguigu',this.test) }
-
若想让自定义事件只能触发一次,可以使用
once
修饰符,或$once
方法。
-
-
触发自定义事件:
this.$emit('atguigu',数据)
-
解绑自定义事件
this.$off('atguigu')
-
组件上也可以绑定原生DOM事件,需要使用
native
修饰符。 -
注意:通过
this.$refs.xxx.$on('atguigu',回调)
绑定自定义事件时,回调要么配置在methods中,要么用箭头函数,否则this指向会出问题!
1.2 方式一: 通过父组件给子组件传递函数类型的props实现
App.vue 父组件
<template>
<div>
<h1 class="title">{{ title + ' ' }}学校名称: {{ schoolName }} </h1>
<!-- 子组件给父组件传递数据,通过父组件给子组件传递函数类型的props实现-->
<School :getSchoolName="getSchoolName"/>
</div>
</template>
<script>
import School from '@/components/School.vue'
export default {
name: 'App',
components: {School},
data() {
return {
title: '你好',
schoolName: ''
}
},
methods: {
getSchoolName(name) {
this.schoolName = name
}
}
}
</script>
School .vue 子组件
<template>
<div class="demo">
<h2>学校名称:{{ name }}</h2>
<h2>学校地址:{{ address }}</h2>
<!-- 点击,子组件向父组件传值 -->
<button @click="sendSchoolName">给APP父组件传递学校名称</button>
</div>
</template>
<script>
export default {
name: 'School',
data() {
return {
name: '尚硅谷atguigu',
address: '北京'
}
},
props: ['getSchoolName'],
methods: {
sendSchoolName() {
this.getSchoolName(this.name)
}
}
}
</script>
<style scoped>
.demo {
background-color: skyblue;
margin-bottom: 30px;
padding: 10px;
}
</style>
1.3 方式二:通过父组件给子组件绑定一个自定义事件实现
App.vue 父组件
<template>
<div>
<h1 class="title">{{ title + ' ' } 学生姓名:{{ studentName }}</h1>
<!-- 通过父组件给子组件绑定一个自定义事件实现,(第一种写法,使用@或v-on)-->
<!-- v-on在谁身上就是再给谁绑定事件, 事件名叫atguigu,getStudentName函数就会被调用 -->
<!--<Student v-on:atguigu="getStudentName"/>-->
<!-- 只触发一次 -->
<!-- <Student @atguigu.once="getStudentName"/>-->
<!-- 通过父组件给子组件绑定一个自定义事件实现,(第二种写法,使用ref)-->
<Student ref="student"/>
</div>
</template>
<script>
import Student from '@/components/Student.vue'
export default {
name: 'App',
components: { Student},
data() {
return {
title: '你好',
studentName: ''
}
},
mounted() {
// this.$refs.student.$on('atguigu', this.getStudentName) // 绑定自定义事件
this.$refs.student.$once('atguigu', this.getStudentName) // 绑定自定义事件(只触发一次)
},
methods: {
getStudentName(name) {
this.studentName = name
},
// 传递多个参数时
//getStudentNames(name, ...params) {
// this.studentName = name
//}
,
add(){
this.number++
},
unbind(){
// 解绑一个
this.$off('atguigu')
// 解绑多个
this.$off(['atguigu', 'demo'])
// 解绑所有的自定义事件
this.$off()
},
death(){
this.$destroy() // 销毁当前student组件的实例,销毁后所有实例的自定义事件全部不奏效。
}
}
}
</script>
<style scoped>
</style>
School .vue 子组件
<template>
<div class="demo">
<h2>学生姓名:{{ name }}</h2>
<h2>学生性别:{{ sex }}</h2>
<h2>当前求和:{{ number }}</h2>
<button @click="sendStudentName">发送学生姓名</button>
<button @click="add">点我number++</button>
<button @click="unbind">解绑aiguigu事件</button>
<button @click="death">销毁当前student组件的实例Vc</button>
</div>
</template>
<script>
export default {
name: 'Student',
data() {
return {
name: '张三',
sex: '男',
number: 0
}
},
methods: {
sendStudentName() {
// 触发事件,传递参数
this.$emit('atguigu', this.name)
//this.$emit('atguigu', this.name, 44, 23, 21)
}
}
}
</script>
<style lang="less" scoped>
.demo {
background-color: pink;
padding: 10px;
}
</style>
2 利用全局事件总线
配置全局事件总线,来达到组件之间的数据通信。例如:父传子,子传父、兄弟之间、子孙之间等等,任意之间的组件通信。
2.1 知识点: 全局事件总线(GlobalEventBus)
-
一种组件间通信的方式,适用于任意组件间通信。
-
安装全局事件总线:
new Vue({ ...... beforeCreate() { Vue.prototype.$bus = this //安装全局事件总线,$bus就是当前应用的vm }, ...... })
-
使用事件总线:
-
接收数据:A组件想接收数据,则在A组件中给$bus绑定自定义事件,事件的回调留在A组件自身。
methods(){ demo(data){......} } ...... mounted() { this.$bus.$on('xxxx',this.demo) }
-
提供数据:
this.$bus.$emit('xxxx',数据)
-
-
最好在beforeDestroy钩子中,用$off去解绑当前组件所用到的事件。
2.2 案例:兄弟之间,Student组件给School组件传递数据
第一步:安装全局事件总线
在main.js中安装全局数据总线(此处的$bus可任意起名,也可以是Vue.prototype.x = this)
//创建vm
new Vue({
el:'#app',
render: h => h(App),
beforeCreate() {
// 安装全局事件总线,$bus就是当前应用的vm
Vue.prototype.$bus = this
}
})
第二步: 在全局事件总线上绑定事件
谁收数据,就谁就绑定事件总线上的事件
在School组件上创建事件hello
<template>
<div class="demo">
<h2>学校名称:{{ name }}</h2>
<h2>学校地址:{{ address }}</h2>
<h2>学生姓名:{{ studentName }}</h2>
</div>
</template>
<script>
export default {
name: 'School',
data() {
return {
name: '尚硅谷atguigu',
address: '北京',
studentName: ''
}
},
mounted() {
// 在$bus全局事件总线上面绑定hello自定义事件
this.$bus.$on('hello', this.demo)
},
beforeDestroy() {
// 在$bus全局事件总线上面销毁hello自定义事件
this.$bus.$off('hello')
},
methods:{
demo(data){
this.studentName = data
}
}
}
</script>
<style scoped>
.demo {
background-color: skyblue;
margin-bottom: 30px;
padding: 10px;
}
</style>
第三步:触发事件
Student组件触发事件
<template>
<div class="demo">
<h2>学生姓名:{{ name }}</h2>
<h2>学生性别:{{ sex }}</h2>
<button @click="sendNameToSchool">发送数据给school</button>
</div>
</template>
<script>
export default {
name: 'Student',
data() {
return {
name: '张三',
sex: '男'
}
},
methods:{
sendNameToSchool(){
// 触发自定义事件hello
this.$bus.$emit('hello', this.name)
}
}
}
</script>
<style lang="less" scoped>
.demo {
background-color: pink;
padding: 10px;
}
</style>
3 利用消息订阅与发布(不推荐)
3.1 知识点:消息订阅与发布
3.2 案例:兄弟之间,Student组件给School组件传递数据
需要数据的人订阅信息
第一步: 安装pubsub.js
npm i pubsub-js
第二步: School组件订阅
<template>
<div class="demo">
<h2>学校名称:{{ name }}</h2>
<h2>学校地址:{{ address }}</h2>
<h2>学生姓名:{{ studentName }}</h2>
</div>
</template>
<script>
import pubsub from 'pubsub-js'
export default {
name: 'School',
data() {
return {
name: '尚硅谷atguigu',
address: '北京',
studentName: ''
}
},
mounted() {
// 订阅
// 方式一写成箭头函数的形式,注意只能是箭头函数this的指向才是Vm
// this.pubId = pubsub.subscribe('hello', (message, name) => {
// console.log('有人发布了hello消息,hello消息的回调执行了', message, name, this)
// })
// 方式二
this.pubId = pubsub.subscribe('hello', this.demo)
},
beforeDestroy() {
// 取消订阅,需要通过this.pubId
pubsub.unsubscribe(this.pubId)
},
methods:{
demo(message, name){
console.log('有人发布了hello消息,hello消息的回调执行了', message, name, this)
this.studentName = name
}
}
}
</script>
<style scoped>
.demo {
background-color: skyblue;
margin-bottom: 30px;
padding: 10px;
}
</style>
第三步: Student组件发布
<template>
<div class="demo">
<h2>学生姓名:{{ name }}</h2>
<h2 class="atguigu">学生性别:{{ sex }}</h2>
<button @click="sendNameToSchool">发送数据给school</button>
</div>
</template>
<script>
import pubsub from 'pubsub-js'
export default {
name: 'Student',
data() {
return {
name: '张三',
sex: '男'
}
},
methods: {
sendNameToSchool() {
// 发布
this.pubId = pubsub.publish('hello', this.name)
}
}
}
</script>
<style lang="less" scoped>
.demo {
background-color: pink;
padding: 10px;
}
</style>