阅读时间预估:8分钟
前端
组件之间通讯是Vue中最经常使用,最基础的部分,一般组件以前的通讯分为如下几种:vue
props $emit v-on
父组件A经过props向子组件B通讯git
接下来咱们经过一个例子来加深以上理解:程序员
自定义一个Son.vue子组件,引入到父组件中 在父组件中定义一个数据github
<template>
<div id="app">
<!-- 前者自定义名称便于子组件调用,后者要传递数据名 -->
<son v-bind:user="user"></son>
</div>
</template>
复制代码
<script>
import Son from './components/Son'
export default {
name: 'app',
components: {
Son,
},
data () {
return { // 父组件定义数据,传递给子组件
user: ["james", "alice", "joho"]
}
},
}
</script>
复制代码
子组件中经过prop来定义父组件传值的值类型,是不是必须以及默认值vuex
<script>
export default {
components: {
},
data () {
return {
};
},
computed: {
},
methods: {
},
props: {
user: { //这个就是父组件中子标签自定义名字
type: Array,
required: true,
default: []
}
},
}
</script>
复制代码
而后在适当的位置将父组件传递过来的数据进行渲染npm
<template>
<div>
<ul>
<li v-for="(item,index) in user"
:key="index">姓名:{{item}}</li>
</ul>
</div>
</template>
复制代码
浏览器打开会显示user里面的值.浏览器
总结:父组件经过props向下传递数据给子组件。注:组件中的数据共有三种形式:data、props、computedbash
核心点app
1.子组件使用this.$emit('fn',param)
向父组件传值
2.父组件经过v-on:fn="fn"
来接受子组件传递过来的值
子组件中:
子组件包含一个点击事件
// 定义一个点击事件
<son v-bind:user="user"
@titleChange="changeTitle">
</son>
复制代码
在点击事件中经过this.$emit()来传递事件
<script>
//import x from ''
export default {
components: {
},
data () {
return {
title: '我是子组件',
toParentData: '我是子组件传递的数据'
};
},
computed: {
},
methods: {
btnClick () {
this.$emit('titleChange', this.toParentData);
}
},
}
</script>
复制代码
父组件中: 经过v-on来接受子组件发出的事件名称:titleChange而且和本身的changeTitle事件绑定
<template>
<div id="app">
<!-- 前者自定义名称便于子组件调用,后者要传递数据名 -->
<son v-bind:user="user"
v-on:titleChange="changeTitle"></son>
<p>{{msg}}</p>
</div>
</template>
复制代码
实现changeTitle方法,改变data中的msg数据
<script>
import Son from './components/Son'
export default {
name: 'app',
components: {
Son,
},
data () {
return {
user: ["james", "alice", "joho"],
msg: '我是父组件显示的内容'
}
},
methods: {
changeTitle (title) {
this.msg = title;
}
}
}
</script>
复制代码
总结:子组件经过events给父组件发送消息,实际上就是子组件把本身的数据发送到父组件。
发现了一个问题,若是孙子组件给爷爷组件传值,经过props
或者$emit
方式是一件很痛苦的事情,须要经过中间的爸爸来作衔接,这样通讯显然会使得组件耦合,同时兄弟组件间的通讯props
,$emit
也实现不了?那么问题来了,如何解决呢?
这里介绍中央事件总线的方式,名字高大上其实就是抽一个公共Vue实例媒介来管理,须要通讯的组件都引入Bus,以后经过分别触发和监听 Bus 事件,进而实现组件之间的通讯和参数传递.
// Bus.js
import Vue from 'vue'
export default new Vue;
复制代码
// ComponentA.vue
<template>
<div>
<b>组件A:</b><button @click="handleBus">传递数值给须要的组件</button>
</div>
</template>
<script>
import Bus from './bus.js'
export default {
methods: {
handleBus () {
Bus.$emit('someBusMessage','来自ComponentA的数据')
}
}
}
</script>
复制代码
// ComponentB.vue
<template>
<div>
<b>组件B:</b><button @click="handleBus">接收组件A的信息</button>
<p>{{message}}</p>
</div>
</template>
<script>
import Bus from './bus.js'
export default {
data() {
return {
message: ''
}
},
created () {
let that = this // 保存当前对象的做用域this
Bus.$on('someBusMessage',function (data) {
that.message = data
})
},
beforeDestroy () {
// 手动销毁 $on 事件,防止屡次触发
Bus.$off('someBusMessage', this.someBusMessage)
}
}
</script>
复制代码
中央总线优势:能够解耦组件,方便兄弟间通讯
$parent
/ $children
& $refs
$parent
/ $children
:指定已建立的实例,在二者之间创建父子关系。子实例能够用 this.$parent
访问父实例,子实例被推入父实例的 $children
中。
$refs
:一个对象,持有注册过 ref
特性的全部 DOM 元素和组件实例。ref
被用来给元素或子组件注册引用信息。引用信息将会注册在父组件的 $refs 对象上。
若是在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;若是用在子组件上,引用就指向组件。
父组件
<template>
<div id="app">
<!-- 前者自定义名称便于子组件调用,后者要传递数据名 -->
<p>{{msg}}</p>
<child-one ref="childOne"></child-one>
<child-two ref="childTwo"></child-two>
<button @click="oneContent">显示child-one传过来的数据</button>
<button @click="twoOneContent">显示hild-two传过来的数据</button>
</div>
</template>
<script>
// 引入子组件
import ChildOne from './components/ChildOne'
import ChildTwo from './components/ChildTwo'
export default {
name: 'app',
components: {
ChildOne,
ChildTwo
},
data () {
return {
msg: '我是父组件',
content: 'James' //子组件要用的数据
}
},
methods: {
// button 的事件响应
oneContent () {
const childOne = this.$refs.childOne;
this.msg = childOne.msg;
},
twoOneContent () {
// 经过$refs取到childTwo
const childTwo = this.$refs.childTwo;
this.msg = childTwo.msg;
}
},
}
</script>
复制代码
子组件1
<template>
<div>
<p>{{title}} 个人父组件是{{content}}</p>
</div>
</template>
<script>
//import x from ''
export default {
components: {
},
data () {
return {
content: '',
title: '我是子组件 childOne',
msg: '我只子组件childOne hello ereryOne'
};
},
mounted () {
// 从父组件里取contet的数据
this.content = this.$parent.content;
},
}
</script>
复制代码
子组件2:
<template>
<div>
<p>{{title}} 个人父组件是{{content}}</p>
</div>
</template>
<script>
//import x from ''
export default {
data () {
return {
content: '',
title: '我是子组件 childTwo',
msg: '我是子组件childTwo hello ereryOne'
};
},
mounted () {
// 加载父组件content的内容
this.content = this.$parent.content;
},
}
</script>
复制代码
npm i pubsub --save
的方式引入pubsub库event-type.js
定义Symbol类型的数据并导出// event-types.js
export const MY_TOPIC = Symbol('MY_TOPIC')
复制代码
pubsub
和 event=type.js
,而且经过如下方式发布事件import PubSub from 'pubsub'
import { MY_TOPIC } from './event-types.js'
PubSub.publish(MY_TOPIC, 'world');
复制代码
pubsub
和 event=type.js
,而且经过如下方式接受事件import PubSub from 'pubsub'
import { MY_TOPIC } from './event-types.js'
PubSub.subscribe(MY_TOPIC, function (msg, data) {
console.log(data)
});
复制代码
Vuex 是Vue官方推荐的一种解决组件中通讯的完美解决方案,也是在项目开发中必用的方案:
认真看完本篇后对照思惟导图能够在脑海里回顾一遍哦,对此块的知识点你会有更深的认识和理解.
若是个人分享对面前的这位大侠有所启发,请不要吝啬手中大拇指,以程序员最高礼遇点赞✨ 评论加分享的方式鼓励我持续分享,也欢迎各位大佬勘误,提出宝贵意见.
关注公众号回复:学习 领取前端最新最全学习资料,也能够进群和大佬一块儿学习交流