之前简单做了一次vue通信方法的培训,在此记录一下培训的内容。

关于vue通信,大家最先想到的方法应该是props、ref、$emit、$parent,还有vuex,因为这也是我在项目中最常用到的方法,其实,还有其他的一些通信方法,下面我来作个简单的介绍:

我主要通过组件类型来介绍:

一、父子组件通信:

(1)父向子传值:

props: 一般用于父组件向子组件进行单向通信

ref:为子组件指定一个索引名称,通过索引来操作子组件,用this.$refs.name 获取到组件实例,可以使用组件的所有方法

$children: 父组件也可以通过this.$children 访问它所有的子组件( 需要注意 $children 并不保证顺序 )

(2)子向父传值 :

$emit:触发父组件的自定义事件 vm.$emit( event, arg )

$parent:通过this.$parent可以直接访问该组件的父实例或组件(得到最近一级的父组件)

父子组件通信实例:

//父组件
<template>
<div>
<div class="box">
<a-button @click="onClick">传参给子组件</a-button>
我是父组件,点击次数:{{ msg }}
<child ref="childRef" :msg="msg" @child-event="watchChildEvent"></child>
</div>
</div>
</template>
<script>
import Child from "./son";
export default {
components: { Child },
data() {
return {
msg: 0
};
},
methods: {
onClick() {
++this.msg;
},
//监听由子组件触发的事件,参数为子组件传来的数据
watchChildEvent(val) {
this.msg = val;
},
//监听由子组件触发的事件,参数为子组件传来的数据
watchParEvent(val) {
this.parMsg = val;
}
},
mounted() {
//父组件调用子组件方法
this.$refs.childRef.getMessage("我是子组件一");
}
};
</script>
//子组件
<template>
<div class="son-box">
<a-button @click="targetClick">通过$emit传参到父组件</a-button><br />
<a-button @click="parClick">2、通过$parent传参到父组件</a-button><br />
我是子组件1,点击次数:{{ msg }}<br />
{{ val }}
</div>
</template>
<script>
export default {
components: {},
props: {
msg: {
type: [String, Number], //类型
default: 0 //可以设置默认值
}
},
data() {
return {
val: ""
};
},
methods: {
//由子组件的事件触发 自定义事件wathChildEvent
targetClick() {
this.$emit("child-event", 20); //参数改为this.msg ??
},
//使用$parent访问父组件(得到最近一级的父组件)
parClick() {
this.$parent.watchParEvent("2、我是使用$parent更改的父级msg");
},
//由父组件的事件触发
getMessage(m) {
console.log(m);
},
},
mounted() {}
};
</script>

二、兄弟组件通信:

不使用 props 和 Vuex 时,可以用什么呢?

eventBus (中央事件总线event Bus),它允许两个子组件之间直接通讯,而不需要涉及父组件。是实现非父子组件通信的一种解决方案。但是当项目较大较复杂时,并不适合。到那时,vuex才是vue给我们提供的最理想的方式。 原理:就是创建一个vue实例,通过一个空的vue实例作为桥梁实现vue组件间的通信。(在Vue2中可谓是最好用的非父子组件之间的通讯手段,但是Vue3宣布取消了,官方推荐的做法是让用户自己寻找使用第三方库,后续有时间会分享一篇vue3如何去实现event Bus)

eventBus 的用法如下:

第一步:项目中创建一个js文件(命名为event-bus.js),引入vue,创建一个vue实例,导出这个实例,代码如下(一共就两行):

 import Vue from 'Vue'
export default new Vue

第二步:在两个需要通信的两个组件中分别引入这个event-bus.js

 import Bus from '这里是你引入event-bus.js的路径' // Bus可自由更换喜欢的名字

第三步:传递数据的组件里通过vue实例方法$emit发送事件名称和需要传递的数据。(发送数据组件)

Bus.$emit('click',data) // 这个click是一个自定义的事件名称,data就是你要传递的数据。

第四步:被传递数据的组件内通过vue实例方法$on监听到事件和接受到数据。(接收数据的组件)这里通常挂载监听在vue生命周期created和mounted当中的一个,具体使用场景需要具体的分析,这里不说这个。

Bus.$on('click',target => {
 console.log(target) //注意:发送和监听的事件名称必须一致,target就是获取的数据,可以不写target。(自己命名)
})

通过以上的四步其实就已经实现了最简单的eventbus的实际应用了。

但是到这儿后,一定要注意一个最容易忽视,又必然不能忘记的东西,那就是清除事件总线eventBus. 不手动清除,它是一直会存在的,这样的话,有个问题就是反复进入到接受数据的组件内操作获取数据,原本只执行一次的获取的操作将会有多次操作。如上我所举的例子,会打印多次传过来的数据。但你想想,实际开发中是不会这么简单的打印这个数据到控制台,本来只会触发并只执行一次,现在变成了多次,这个问题就非常严重了,你们各种脑补具体的项目开发场景吧。

第五步:在vue生命周期beforeDestroy或者destroyed中用vue实例的$off方法清除eventBus

beforeDestroy(){
bus.$off('click')
}

 

三、跨多层级组件通信

A-B-C,三个组件,从爷组件A传参到孙组件C,应该怎么传呢?

(1)通过props一层层传递过去,传到子,给传给孙

(2)用vuex 共享状态(开发大型单页应用)

(3)使用$attrs传参,$listeners监听事件,或者用provide 和 inject

 1、$attrs和$listeners的介绍:

  • $attrs是在vue的2.40版本以上添加的。
  • 所有的非props属性,都可以通过 v-bind="$attrs" 传入内部组件——在创建高级别的组件时非常有用。
  • 多层组件传参使用$attrs,可以使代码更加美观,更加简洁,维护代码的时候更方便。如果使用普通的父子组件传参prop会很繁琐;如果使用vuex会大材小用,只是在这几个组件中使用,没必要使用vuex;使用事件总线eventBus,使用不恰当的话,有可能会出现事件多次执行。
  • 所有组件上的方法绑定子组件都可以通过$listeners接收
  • 详情可查看:vue.js-$attrs
注意:
1、vue2中使用$attrs从父组件传递数据给子组件嵌套组件,父组件通过通过$listeners监听子组件的事件
2、vue3把把$attrs和$listeners统一合并到$attrs中

  

props的劣势: 父组件传入子组件属性,但子组件没有接收称为非props属性,非props属性默认会加到子组件标签最外层

inheritAttrs: false的含义是不希望本组件的根元素继承父组件的attribute,同时父组件传过来的属性(没有被子组件的props接收的属性),也不会显示在子组件的dom元素上,但是在组件里可以通过其$attrs可以获取到没有使用的注册属性, inheritAttrs: false是不会影响 style 和 class 的绑定

$listeners的实例:

所有组件上的方法绑定子组件都可以通过$listeners接收。它可以通过 v-on="$listeners" 将所有的方法又绑定到组件相应标签,传入内部组件——在创建更高层次的组件时非常有用。

2、provide 和 inject的介绍与实例:

provide和inject是在2.2.0 版本新增的,主要为高阶插件/组件库提供用例。这对选项需要一起使用,以允许一个祖先组件向其所有的子孙后代注入一个依赖,不论组件的层次有多深,并在起上下游关系成立的时间里始终生效。

provide 选项应该是一个对象或返回一个对象的函数。该对象包含可注入其子孙的属性。

inject 选项应该是:一个字符串数组,或一个对象(属性值是一个对象时,包含from和default默认值)

注意:provide和inject绑定并不是可响应的。这显然不是设计的失误,而是刻意的。如果要详细了解,请参考:API — Vue.js

我们在上级组件中设置了一个provide:foo,值为beijing,它的作用就是将foo这个变量提供给它的所有下级组件。而在下级组件中通过inject注入了从上级组件中提供的foo变量,那么在下级组件中,就可以直接通过this.foo来访问了

provide 和 inject的实例:

如果想要获取父组件parent.vue 的多个属性或方法时,我们应该怎么传呢?是一个个的定义参数传过去吗?

parent.vue作为一个最外层的根组件,用来存储所有需要的全局数据和状态。我们可以把整个parent.vue实例通过provide对外提供。那么,所有的子组件、孙组件都能共享其数据,方法等。

 四、VUEX状态管理

内容太多,将在下篇单独做介绍

vue 通信:父子通信、兄弟通信、跨多层通信、vuex状态管理的更多相关文章

  1. vue第十八单元(单向数据流 vuex状态管理)

    第十八单元(单向数据流 vuex状态管理) #课程目标 1.理解什么是数据管理模式 2.什么是vuex 3.什么时候使用vuex 4.vuex安装及工作原理 5.vuex语法 #知识点 1.首先来看下 ...

  2. 前端MVC Vue2学习总结(八)——Vue Router路由、Vuex状态管理、Element-UI

    一.Vue Router路由 二.Vuex状态管理 三.Element-UI Element-UI是饿了么前端团队推出的一款基于Vue.js 2.0 的桌面端UI框架,手机端有对应框架是 Mint U ...

  3. 前端Vue框架-vuex状态管理详解

    新人报道!多多关照-多提宝贵意见 谢谢- vuex理解 采用集中式存储管理模式.用来管理组件的状态,并以自定义规则去观测实时监听值得变化. 状态模式管理理解 属性 理解 state 驱动应用的数据源 ...

  4. Vuex状态管理——任意组件间通信

    核心概念 在Vue中实现集中式状态(数据)管理的一个Vue插件,对vue应用中多个组件的共享状态进行集中式的管理(读/写),也是一种组件间通信的方式,且适用于任意组件间通信. 每一个 Vuex 应用的 ...

  5. vue组件化开发-vuex状态管理库

    Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式.它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化.Vuex 也集成到 Vue 的官方调试工具 ...

  6. vue从入门到进阶:Vuex状态管理(十)

    Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式.它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化. 在 Vue 之后引入 vuex 会进行自动 ...

  7. 应用四:Vue之VUEX状态管理

    (注:本文适用于有一定Vue基础或开发经验的读者,文章就知识点的讲解不一定全面,但却是开发过程中很实用的) 概念:Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式.它采用集中式存储管理应 ...

  8. vue项目--vuex状态管理器

    本文取之官网和其他文章结合自己的理解用简单化的语言表达.用于自己的笔记记录,也希望能帮到其他小伙伴理解,学习更多的前端知识. Vuex 是什么? Vuex 是一个专为 Vue.js 应用程序开发的状态 ...

  9. 【Flutter学习】组件通信(父子、兄弟)

    一,概述 flutter一个重要的特性就是组件化.组件分为两种状态,一种是StatefulWidget有状态组件,一种是StatelessWidget无状态组件. 无状态组件不能更新状态,有状态组件具 ...

随机推荐

  1. js trim()方法

    从字符串中移除前导空格.尾随空格和行终止符. 语法 stringObj.trim() 参数 stringObj 必选.String 对象或字符串.trim 方法不修改该字符串. 返回值 已移除前导空格 ...

  2. Serializable接口中serialVersionUID字段的作用

    序列化运行时使用一个称为 serialVersionUID 的版本号与每个可序列化类相关联,该序列号在反序列化过程中用于验证序列化对象的发送者和接收者是否为该对象加载了与序列化兼容的类. 如果接收者加 ...

  3. Linux-一次执行多个命令 ; && ||

    一次执行多个命令,多个命令之间用:号隔开 cmd1;cmd2:cmd3 这样前后执行的时候没有依赖性,如果有下列要求呢 1. cmd1执行失败那就不要执行后面的命令 2. cmd1失败了才去指令后面的 ...

  4. Endnote

    #Entnote无法使用Find all test 搜索到sciencedirect的文章(或Elsevier 爱思唯尔) 下面是来自endnote官方论坛的原文Find full text for ...

  5. 如何通过opensea-js获取OpenSea的数据

    OpenSea作为NFT最大的交易平台,随着NFT的火热之后,热度也是出现翻天覆地的变化.作为开发人员肯定好奇有没有可以与opensea交互的包来开发相关的工具或者快速获取opensea的数据.别急, ...

  6. 帆软报表(finereport)根据提供的数据求出该日期所在的季度

    根据当前日期求字段中日期的季度 Oracle数据库 select T1.INDEXCODE ,T1.CREATETIME ,CASE when T1.CREATETIME = (case when t ...

  7. 《STL源码剖析》学习半生记:第一章小结与反思

    不学STL,无以立.--陈轶阳 从1.1节到1.8节大部分都是从各方面介绍STL, 包括历史之类的(大致上是这样,因为实在看不下去我就直接略到了1.9节(其实还有一点1.8.3的内容)). 第一章里比 ...

  8. 字符集编码(上):Unicode 之前

    计算机起初是设计用来做数学计算的,Computer 一词英文原意是"计算员"--在计算机发明之前,计算员是一个独立的职业,专门做各种数学用表的计算,如测量和天文领域的三角函数表.对 ...

  9. suse 12 二进制部署 Kubernetets 1.19.7 - 第08章 - 部署kube-scheduler组件

    文章目录 1.8.部署kube-scheduler 1.8.0.创建kube-scheduler请求证书 1.8.1.生成kube-scheduler证书和私钥 1.8.2.创建kube-schedu ...

  10. netty介绍与构成

    什么是 Netty Netty 是一个利用 Java 的高级网络的能力,隐藏其背后的复杂性而提供一个易于使用的 API 的客户端/服务器框架.Netty 提供高性能和可扩展性,让你可以自由地专注于你真 ...