组件之间通信可以用下图表示:

组件关系可分为父子组件通信、兄弟组件通信、跨级组件通信。

一、自定义事件

当子组件需要向父组件传递数据时,就要用到自定义事件。

子组件用$emit ()来触发事件,父组件用$on()来监昕子组件的事件。

父组件可以直接在子组件的自定义标签上使用v-on 来监昕子组件触发的自定义事件,如:

        <div id="app9">
<p>总数:{{total}}</p>
<my-component9 @add="getTotal" @cut="getTotal"></my-component9>
</div>
Vue.component('my-component9',{
template: '<div>' +
' <button @click="increase">+1</button>' +
' <button @click="reduce">-1</button>' +
'</div>',
data: function(){
return {
count: 0
}
},
methods:{
increase: function(){
this.count++;
this.$emit('add',this.count)  //广播的事件名和数据
},
reduce: function(){
this.count--;
this.$emit('cut',this.count)  //广播的事件名和数据
}
}
}); var app9 = new Vue({
el: '#app9',
data:{
total: 0
},
methods:{
getTotal: function(count){
this.total = count;
}
}
});

二、使用v-model

Vue2 .x 可以在自定义组件上使用v-model 指令,直接看一个事例:

        <div id="app10">
<p>总数:{{total}}</p>
<my-component10 v-model="total"></my-component10>  //这个地方v-model实际是一个语法糖,可以直接理解为接收到广播input里面的数据(this.total=count)。
</div>
Vue.component('my-component10',{
template: '<div>' +
'<button @click="increase">+1</button>' +
'<button @click="reduce">-1</button>' +
'</div>',
data: function(){
return {
count: 0
}
},
methods:{
increase: function(){
this.count++;
this.$emit('input',this.count)  //注意这个地方,广播的事件名称为特殊的input
},
reduce: function(){
this.count--;
this.$emit('input',this.count)  //注意这个地方,广播的事件名称为特殊的input
}
}
}); var app10 = new Vue({
el: '#app10',
data:{
total: 0
}
});

v-model 还可以用来创建自定义的表单输入组件, 进行数据双向绑定,例如:

        <div id="app11">
<p>总数:{{total}}</p>
<my-component11 v-model="total"></my-component11>
<button @click="reduce">-1</button>
</div>
Vue.component('my-component11', {
props: ['value'],  //使用v-model的表单组件时,父组件通过value来进行传值
template: '<input :value="value" @input="updateValue">',
methods: {
updateValue: function(event){
this.$emit('input', event.target.value);
}
}
}); var app11 = new Vue({
el: '#app11',
data:{
total: 0
},
methods:{
reduce: function(){
this.total--
}
}
});

父组件的total发生变化时,会通过传递value值,影响子组件input中的value值,而子组件改变自己input中的value值,又会广播给父组件,影响父组件中的total值。

实现这样一个具有双向绑定的v -model 组件要满足下面两个要求:

•接收一个value 属性。
• 在有新的value 时触发input 事件。

三、非父子组件通信

在Vue . 2.x 中, 推荐使用一个空的Vue 实例作为中央事件总线( bu s ),也就是一个中介。

直接看一个事例:

        <div id="app12">
<p>{{message}}</p>
<my-component12></my-component12>
</div>
var bus = new Vue();

Vue.component('my-component12',{
template: '<button @click="updateMessage">传递事件信息</button>',
methods: {
updateMessage: function(){
bus.$emit('updateMessage','更新我的组件信息'); //利用中介bus传播事件
}
}
}); var app12 = new Vue({
el: '#app12',
data:{
message: ''
},
mounted: function(){
var _this = this; //这一步赋值必须有
bus.$on('updateMessage',function(data){ //利用中介bus接收事件
_this.message = data;
})
}
});

在app 初始化时,也就是在生命周期mounted 钩子函数里监听了来自bus 的事件updateMessage(mounted挂载这一步相当于在两个组件直间提前安排了一个中介,当两个组件通信时,就可以通过该中介相互传递消息了) ,

而在组件my-component12中,点击按钮会通过bus 把事件updateMessage发出去,此时app 就会接收到来自bus 的事件,进而在回调里完成自己的业务逻辑。

这种方法巧妙而轻量地实现了任何组件间的通信,包括父子、兄弟、跨级,而且Vue 1.x 和Vue 2.x 都适用。

四、父链与子组件索引

除了中央事件总线bus 外,还有两种方法可以实现组件间通信:父链和子组件索引。

在子组件中,使用this.$parent 可以直接访问该组件的父实例或组件,父组件也可以通过this.$children 访问它所有的子组件,而且可以递归向上或向下无线访问, 直到根实例或最内层的组件。

4.1父链

        <div id="app13">
<p>{{message}}</p>
<my-component13></my-component13>
</div>
Vue.component('my-component13',{
template: '<button @click="updateMessage">通过父链直接修改数据</button>',
methods: {
updateMessage: function(){
this.$parent.message = '来自组件my-component13的内容'  //通过this.$parent直接修改父组件的内容
}
}
}); var app13 = new Vue({
el: '#app13',
data:{
message: ''
}
});

尽管V ue 允许这样操作,但在业务中, 子组件应该尽可能地避免依赖父组件的数据,更不应该去主动修改它的数据,因为这样使得父子组件紧藕合,理想情况下,只有组件自己能修改它的状态。

4.2 子组件索引

当子组件较多时, 通过this.$children 来一一遍历出我们需要的一个组件实例是比较困难的,尤其是组件动态渲染时,它们的序列是不固定的。Vue 提供了子组件索引的方法,用特殊的属性ref来为子组件指定一个索引名称。

        <div id="app14">
<p>{{message}}</p>
<my-component14 ref="com14"></my-component14>
<button @click="handleRef">通过ref获取子组件实例</button>
</div>
Vue.component('my-component14',{
template: '<div>子组件</div>',
data: function(){
return {
message: '子组件内容'
}
}
}); var app14 = new Vue({
el: '#app14',
data:{
message: ''
},
methods: {
handleRef: function(){
this.message = this.$refs.com14.message; //通过$refs获取子组件实例
}
}
});

在父组件模板中,子组件标签上使用ref 指定一个名称,井在父组件内通过this.$refs 来访问指定名称的子组件。

$refs 只在组件渲染完成后才填充,并且它是非响应式的. 它仅仅作为一个直接访问子组件的应急方案,应当尽量避免在模板或计算属性中使用$refs。

vue组件详解(三)——组件通信的更多相关文章

  1. Angular6 学习笔记——组件详解之组件通讯

    angular6.x系列的学习笔记记录,仍在不断完善中,学习地址: https://www.angular.cn/guide/template-syntax http://www.ngfans.net ...

  2. react router @4 和 vue路由 详解(三)react如何在路由里面定义一个子路由

    完整版:https://www.cnblogs.com/yangyangxxb/p/10066650.html 5.react如何在路由里面定义一个子路由?   a.引入在需要子路由的页面引入Rout ...

  3. Angular6 学习笔记——组件详解之模板语法

    angular6.x系列的学习笔记记录,仍在不断完善中,学习地址: https://www.angular.cn/guide/template-syntax http://www.ngfans.net ...

  4. vue.js基础知识篇(6):组件详解

    第11章:组件详解 组件是Vue.js最推崇也最强大的功能之一,核心目标是可重用性. 我们把组件代码按照template.style.script的拆分方式,放置到对应的.vue文件中. 1.注册 V ...

  5. OpenStack各组件详解和通信流程

    一.openstack由来 openstack最早由美国国家航空航天局NASA研发的Nova和Rackspace研发的swift组成.后来以apache许可证授权,旨在为公共及私有云平台建设.open ...

  6. Android笔记——四大组件详解与总结

     android四大组件分别为activity.service.content provider.broadcast receiver. ------------------------------- ...

  7. Tomcat系列之服务器的安装与配置以及各组件详解

    Tomcat系列之服务器的安装与配置以及各组件详解 大纲 一.前言 二.安装与配置Tomcat 三.Tomcat 目录的结构 四.Tomcat 配置文件 注,本文的测试的操作系统为CentOS 6.4 ...

  8. OpenStack的Trove组件详解

    一:简介     一.背景 1. 对于公有云计算平台来说,只有计算.网络与存储这三大服务往往是不太够的,在目前互联网应用百花齐放的背景下,几乎所有应用都使用到数据库,而数据库承载的往往是应用最核心的数 ...

  9. Android中Intent组件详解

    Intent是不同组件之间相互通讯的纽带,封装了不同组件之间通讯的条件.Intent本身是定义为一个类别(Class),一个Intent对象表达一个目的(Goal)或期望(Expectation),叙 ...

  10. Echars 6大公共组件详解

    Echars 六大组件详解 : title  tooltip toolbox legend  dataZoom visualMap 一.title标题详解 myTitleStyle = { color ...

随机推荐

  1. IDEA的配置

    一.使用配置 转自:http://blog.csdn.net/qq_27093465/article/details/52918873 setting: 设置外观和字体: 设置编辑器快捷键:   自动 ...

  2. 如何在原生微信小程序中实现数据双向绑定

    官网:https://qiu8310.github.io/minapp/ 作者:Mora 在原生小程序开发中,数据流是单向的,无法双向绑定,但是要实现双向绑定的功能还是蛮简单的! 下文要讲的是小程序框 ...

  3. 关于win8/win8.1系统不能调节亮度的解决办法

    有时候我们重装了win8系统之后开始可以调节亮度,但是再重新安装了显卡驱动之后发现不能调节亮度了,解决办法就是添加一项注册表. 下载地址:http://7xnarc.com1.z0.glb.cloud ...

  4. android 获取wifi列表,如果你忽略了这个细节,可能你的软件会崩溃

    一:业务描述 最近公司有一个小需求,用户点击wifi扫描按钮(注意:是用户主动点击wifi扫描按钮),app去扫描附近的wifi,显示在listView中,仅此而已,app都不用去连接某个wifi,看 ...

  5. 20165226 预备作业3 Linux安装及学习

    20165226 预备作业3 Linux安装及学习 Linux安装 一.下载安装VirtualBox 1.首先在官网下载,点开基于VirtualBox虚拟机安装Ubuntu图文教程 找到版本进行下载安 ...

  6. 《Java2 实用教程(第五版)》学习指导

    <Java2 实用教程(第五版)> 第1章Java入门 主要内容:P1 1.1Java的地位:P1 1.2Java的特点:P2 1.3安装JDK:P5 1.4Java程序的开发步骤:P8 ...

  7. 将 Shiro 作为应用的权限基础 三:基于注解实现的授权认证过程

    授权即访问控制,它将判断用户在应用程序中对资源是否拥有相应的访问权限. 如,判断一个用户有查看页面的权限,编辑数据的权限,拥有某一按钮的权限等等. 一.用户权限模型 为实现一个较为灵活的用户权限数据模 ...

  8. java人民币读法转换

    实现浮点数转换成人民币读法字符串 编写一个程序,将浮点数转换成人民币读法字符串,例如,将1006.333转换为壹千零陆元叁角叁分. 题意分析: 将浮点数分成整数部分和小数部分,分开处理整数部分和小数部 ...

  9. 分布式代码管理系统GIT

    1.1Git安装 CentOS上   yum install -y epel-release; yum install git Ubuntu上    apt-get install git Windo ...

  10. 如何打包静态库.a文件 iOS

    代码调试好了开始打包成sdk,下面是将要打包的FRSDK代码(FRSDK.h暴露在外面有别人调用) 1.创建新工程(Xcode File-New-Project) 2.把下面的红色框的东西移除 3.将 ...