vue 组件通信的几种方式
前言
在vue中, 组件的关系不外乎以下三种:
组件是需要通信的,在开发中,常用到的通信方式有:vuex、eventBus、以及props与emit、$parent与$children,除此之外,还有provide与inject、$attrs与$listeners等。
一、vuex
这个相信大家用的很多了,简单回顾一下:
- State:放状态的地方
- Mutation:唯一修改状态的地方,不支持异步
- Action:通过调用Mutation中的方法来达到修改状态的目的,支持异步
- Getter:可以理解为计算属性
- Module:模块,每个模块拥有自己的 state、mutation、action、getter
简单的使用这里不赘述,提一下module里面的命名空间。
如果希望你的模块具有更高的封装度和复用性,你可以通过添加 namespaced: true 的方式使其成为带命名空间的模块。当模块被注册后,它的所有 getter、action 及 mutation 都会自动根据模块注册的路径调整命名
这样,在使用的时候我们就可以这样用了:
二、eventBus
这个称为‘事件总线’,简单看下是怎么使用的:
初始化
首先是初始化一个eventBus,可以绑定到vue原型上,也可以绑定到window对象上,还可以抽出来当做一个模块,在需要的时候再引入。这里直接绑定到vue原型上:
创建事件和删除事件
在需要的组件上创建和删除事件:
触发事件
最后就是在需要的地方触发事件了
三、props/emit
这个不用多说了,父子通信用的最多的应该就是这个了。当然,如果以子组件为跳板,也可以做到祖孙之间通信,不过比较麻烦。不建议这样操作。
四、$parent/$children
$parent直接访问的就是父实例,而$children则返回的是实例数组。所以我一般都是$parent搭配$refs使用。
五、$attrs/$listeners
这两个可能会用的比较少,来看下官网的介绍:
怎么理解呢,简单来讲就是,$attrs接收除了prop、style、class之外的所有绑定属性,$listeners则接收除了被.native修饰的所有绑定事件。具体来看下例子:
<template><div><p>父组件</p><input type="text" v-model="formData.inputValue" /><p>子组件</p><Son:inputValue="formData.inputValue":otherValue="otherValue"@success="success"@input.native="handleInput"v-bind="$attrs"v-on="$listeners"></Son></div>
</template>
<script>
import Son from "./son.vue";
export default {components: { Son },provide() {return {father: this.formData,};},data() {return {formData: {inputValue: "123",},otherValue: 999,};},methods: {success(data) {console.log(data);},handleInput() {},},
};
</script>
<template><div><input type="text" v-model="inputValue" @change="handleChange" /></div>
</template>
<script>
export default {props: {inputValue: String,},created() {console.log(this.$attrs, "son---$attrs");console.log(this.$listeners, "son---$listeners");},methods: {handleChange() {this.father.inputValue = this.inputValue;},},
};
</script>
按照之前的理解,$attrs应该只能接收到otherValue,$listeners则只能接收到success事件,看下打印结果:
结果确实也是这样的。除此之外,还可传递给孙组件:
<template><div><input type="text" v-model="inputValue" @change="handleChange" /><GrandSon v-bind="$attrs" v-on="$listeners"></GrandSon></div>
</template>
<script>
import GrandSon from "./grandSon.vue";
export default {components: { GrandSon },props: {inputValue: String,},created() {console.log(this.$attrs, "son---$attrs");console.log(this.$listeners, "son---$listeners");},methods: {handleChange() {this.father.inputValue = this.inputValue;},},
};
</script>
<template><div><input type="text" v-model="inputValue" @change="handleChange" /></div>
</template>
<script>
export default {props: {inputValue: String,},created() {console.log(this.$attrs, "grandSon---$attrs");console.log(this.$listeners, "grandSon---$listeners");},methods: {handleChange() {this.father.inputValue = this.inputValue;},},
};
</script>
通过这种方式,祖孙之间也实现了通信。
六、provide/inject
provide/inject可以在一个祖先组件中向它的所有后辈组件注入一个依赖,只要上下游关系成立就能生效。简单的理解就是provide是注入数据,inject是获取数据。所以provide是用于父组件,inject是用于子孙组件。provide应该是一个对象或者返回一个对象的函数,inject应该是一个字符串数组或者一个对象。官网提到这么一句话:
提示:provide 和 inject 绑定并不是可响应的。这是刻意为之的。然而,如果你传入了一个可监听的对象,那么其对象的 property 还是可响应的。
这句话怎么理解呢?字面理解就是你要想在上下游传递的那个数据是可响应的,那么就应该以对象的形式传递,先试一下以基本数据类型的形式传递,看下例子:
父组件:
<template><div><p>父组件</p><input type="text" v-model="inputValue" /><p>子组件</p><Son></Son><p>孙组件</p><GrandSon></GrandSon></div>
</template>
<script>
import Son from "./son.vue";
import GrandSon from "./grandSon.vue";
export default {components: { Son, GrandSon },provide() {return {father: this.inputValue,};},data() {return {inputValue: "123",};},
};
</script>
子组件:
<template><div><input type="text" v-model="inputValue" @change="handleChange" /></div>
</template>
<script>
export default {inject: ["father"],data() {return {inputValue: "",};},watch: {father(val) {console.log(val, "val");this.inputValue = val;},},created() {console.log(this, "this");},methods: {handleChange() {this.father.inputValue = this.inputValue;},},
};
</script>
在子组件打印this:
可以看到,父组件的inputValue值是被注入到子组件当中的。但却监听不到这个father。
然后,我们改成以对象的形式进行注入:
<template><div><p>父组件</p><input type="text" v-model="formData.inputValue" /><p>子组件</p><Son></Son><p>孙组件</p><GrandSon></GrandSon></div>
</template>
<script>
import Son from "./son.vue";
import GrandSon from "./grandSon.vue";
export default {components: { Son, GrandSon },provide() {return {father: this.formData,};},data() {return {formData: {inputValue: "123",},};},
};
</script>
<template><div><input type="text" v-model="inputValue" @change="handleChange" /></div>
</template>
<script>
export default {inject: ["father"],data() {return {inputValue: "",};},watch: {'father.inputValue'(val){console.log(val, "val");this.inputValue = val;},},created() {console.log(this, "this");},methods: {handleChange() {this.father.inputValue = this.inputValue;},},
};
</script>
这个时候我们看下打印的this以及效果:
这样就可以实现数据的响应了。这里有一个点需要注意,如果在父组件中将整个父组件的this注入到后代组件中,在后代组件中是不能通过深度监听来监听这个注入的对象的,会报堆栈溢出的错误。所以这里我用的是this.formData
的形式注入。这样在子孙组件中可以通过'father.inputValue'
这样的形式监听,也可以通过这样的形式:
father: {handler(val) {console.log(val);},deep: true,},
至于为什么会导致这个问题,我们先看下深度监听的实现方式:
这段注释什么意思呢,简单理解就是vue是通过递归遍历对象里面的每一个属性,将是对象的属性收集起来进行监听。众所周知,递归是很容易引起堆栈溢出的,而看下this对象就不难理解为什么会导致堆栈溢出了(太多了,而且是层层嵌套下去的)。
以上就是Vue组件通信的几种方式,如果还要在扯一扯,浏览器的缓存也可以作为一种手段。。。
vue 组件通信的几种方式相关推荐
- Vue组件通信的五种方式
Vue组件通信的五种方式 文章目录 Vue组件通信的五种方式 一. props/$emit(父子通信) 二. vuex(组件之间通信) 三. 事件总线EventBus(组件之间通信) 四. provi ...
- vue组件通信的几种方式
vue组件通信的几种方式 最近用vue开发项目,记录一下vue组件间通信几种方式 第一种,父子组件通信 一.父组件向子组件传值 1.创建子组件,在src/components/文件夹下新建一个Chil ...
- vue组件通信的八种方式
一.props / $emit 父组件通过props的方式向子组件传递数据,而通过$emit 子组件可以向父组件通信. 1. 父组件向子组件传值 下面通过一个例子说明父组件如何向子组件传递数据:在子组 ...
- vue组件通信的几种方法
vue中我们最常使用的就是父子之间的通信还有全局数据管理vuex了,下面粗略说一下vue组件通信的几种方法 组件通信的几种方式 1.父子组件通信 2.兄弟组件通信 3.跨多层级组件通信 4.任意组件( ...
- 【vue】vue组件传值的三种方式
前言 vue的组件传值分为三种方式:父传子.子传父.非父子组件传值 引用官网的一句话:父子组件的关系可以总结为 prop 向下传递,事件向上传递 父组件通过 prop 给子组件下发数据,子组件通过事件 ...
- laydate组件 无法传值_Vue组件通信的几种方式
组件是 vue.js最强大的功能之一,而组件实例的作用域是相互独立的,这就意味着不同组件之间的数据无法相互引用.一般来说,组件可以有以下几种关系: 组件之间的关系 如上图所示,A 和 B.B 和 C. ...
- vue组件传值的12种方式
Vue组件间的12种传值方式 当做到比较大的项目时,一个vue文件里面可能要包含上千行代码,这样不利于后期维护与问题定位,抽离成组件就尤其重要了,我在项目中遇到组件的值如何传递的问题,刚开始接触的时候 ...
- React中组件通信的几种方式
首次发表在个人博客 需要组件之进行通信的几种情况 父组件向子组件通信 子组件向父组件通信 跨级组件通信 没有嵌套关系组件之间的通信 1. 父组件向子组件通信 React数据流动是单向的,父组件向子组件 ...
- Vue父子组件通信的三种方式 props、@eventName、$on
前言 vue 开发中,免不了会用到父子组件的通信,比如调用父类组件的方法或者变量:再比如父组件调用子组件的方法:父子组件相互传递数据等,本文主要通过讲解 三种方式(props.evnetName.ev ...
最新文章
- HDU 6156 Palindrome Function 数位DP
- 大学生计算机课程考试试题,大学生计算机基础课程考试系统研究与实现
- java单词按字典排序_最终Java日志字典:开发人员最常记录的单词是什么?
- gradle-com.android.build.api.transform.TransformException:Error while generating the main dex list
- Version Control
- 天池-新冠疫情相似句对判定大赛top6方案及源码
- SQL语法中的JOIN类型
- c语言判断二叉树是不是二叉排序树_判断
- tomcat管理主机
- 通过IE私有滤镜让IE6 7 8支持背景透明,内容不透明效果
- h5案例欣赏及分析_2019下半年,10个优秀H5案例参考
- 微信小程序蓝牙连接TSPL打印机打印图片思路
- 曼妙音色要靠煲 多媒体音箱煲机大法
- Jade平台的下载与原装
- Spark机器学习实验
- T32 simulator
- Fuchsia OS 编译教程 2019 年版
- 《运营力——微信公众号 设计 策划 客服 管理 一册通》导读
- Java入门教程(视频)
- 计算机网络中请求超时是什么意思,请求超时什么意思
热门文章
- Android 区间SeekBar
- 2023最新 Office2021专业增强版 手把手教你安装激活教程
- python ks检验_python KS-检验(Kolmogorov-Smirnov test) -- 检验数据是否符合某种分布...
- 浏览器触发reflow(回流)的操作
- 要是我考上北大了.........
- 旋转矩阵表示姿态XYZ坐标轴关系
- Android 魅族手机消息不显示(进收纳盒)和始终显示一条推送
- 方块与收纳盒-计数dp
- 如何使用口径正确订购电子书系列
- 医院病房E-R图及关系模式