【Vue2从入门到精通】深入浅出,带你彻底搞懂Vue2组件通信的9种方式

在这里插入图片描述

文章目录

  • 人工智能福利文章
  • Vue组件间通信分类
  • 1.props / $emit
    • 1.1 父组件向子组件传值
    • 1.2 子组件向父组件传值
  • 2.$parent / $children
  • 3.ref / $refs
    • 3.1 ref作用于组件
    • 3.2 ref作用于Html标签
    • 3.3 $nextTick()
  • 4.EventBus ($emit / $on)
    • 4.1 初始化
    • 4.2 发送事件
    • 4.3 接收事件
    • 4.4 移除事件监听者
  • 5. a t t r s / attrs/ attrs/listeners
  • 6.provide / inject
  • 7.Vuex
    • 7.1 Vuex 的状态存储是响应式的
    • 7.2 Vuex模块简介
  • 8. localStorage或者sessionStorage
  • 9.slot
  • 总结
  • 写在最后

人工智能福利文章

  • 【分享几个国内免费可用的ChatGPT镜像】
  • 【10几个类ChatGPT国内AI大模型】
  • 【用《文心一言》1分钟写一篇博客简直yyds】
  • 【用讯飞星火大模型1分钟写一个精美的PPT】

Vue组件间通信分类

Vue组件间通信主要指以下 3 类:

父子组件通信、隔代组件通信、兄弟组件通信

下面我们分别介绍每种通信方式且会说明此种方法可适用于哪类组件间通信。

1.props / $emit

适用于父子组件通信

这种方法是 Vue 组件的基础。

1.1 父组件向子组件传值

下面通过一个例子说明父组件如何向子组件传递数据:在子组件article.vue中如何获取父组件section.vue中的数据articles

// 父组件 section.vue<template><div class="section"><com-article :articles="articleList"></com-article></div></template><script>import comArticle from './article.vue'export default {components: { comArticle },data() {return {articleList: ['水浒传', '红楼梦','西游记', '三国演义']}}}</script>// 子组件 article.vue<template><div><span v-for="(item, index) in articles" :key="index">{{item}}         </span></div></template><script>export default {props: ['articles']}</script>

1.2 子组件向父组件传值

$emit绑定一个自定义事件, 当这个语句被执行时, 就会将参数args传递给父组件,父组件通过v-on监听并接收参数。 通过一个例子,说明子组件如何向父组件传递数据。 在上个例子的基础上, 点击页面渲染出来的ariticle的item, 父组件中显示在数组中的下标

//  父组件 section.vue<template><div class="section"><com-article :articles="articleList" @onEmitIndex="onEmitIndex"></com-article><p>{{currentIndex}}</p></div></template><script>import comArticle from './article.vue'export default {components: { comArticle },data() {return {currentIndex: -1,articleList: ['水浒传', '红楼梦','西游记', '三国演义']}},methods: {onEmitIndex(idx) {this.currentIndex = idx}}}</script><template><div><div v-for="(item, index) in articles" :key="index" @click="emitIndex(index)">{{item}}</div></div></template><script>export default {props: ['articles'],methods: {emitIndex(index) {this.$emit('onEmitIndex', index)}}}</script>

2.$parent / $children

适用于父子组件通信

$parent / $children:访问父 / 子实例

// 父组件中<template><div class="hello_world"><div>{{msg}}</div><com-a></com-a><button @click="changeA">点击改变子组件值</button></div></template><script>import ComA from './comA.vue'export default {components: { ComA },data() {return {msg: 'hello world'}},methods: {changeA() {// 获取到子组件Athis.$children[0].messageA = 'this is new value'}}}</script>// 子组件中<template><div class="com_a"><span>{{messageA}}</span><p>获取父组件的值为:  {{parentVal}}</p></div></template><script>export default {data() {return {messageA: 'this is old'}},computed:{parentVal(){return this.$parent.msg;}}}</script>

3.ref / $refs

ref 被用来给元素或子组件注册引用信息, 引用信息将会注册在父组件的 $refs 对象上,如果是在普通的DOM元素上使用,引用指向的就是 DOM 元素,如果是在子组件上,引用就指向组件的实例。

$refs是一个对象,持有已注册过 ref的所有的子组件。

3.1 ref作用于组件

<div id="app"><navbar></navbar><pagefooter></pagefooter>
</div>
Vue.component('navbar',{template:'#navbar',data:function () {return {navs:[]}}
});Vue.component('pagefooter',{template:'#pagefooter',data:function () {return {footer:''}}
});
new Vue({el:'#app',mounted:function () {//ready,//这里怎么直接访问navbar的navs和pagefooter的footer值呢,}
})

这就用到ref了
修改组件

<div id="app"><navbar ref="navbar"></navbar><pagefooter ref="pagefooter"></pagefooter>
</div>
new Vue({el:'#app',mounted:function () {//ready,//这里怎么直接访问navbar的navs和pagefooter的footer值呢,console.log(this.$refs.navbar.navs);console.log(this.$refs.pagefooter.footer);}
})

通过ref和refs,父组件可以轻松获取子组件的信息。

3.2 ref作用于Html标签

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title><script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
</head>
<body>
<div id="app"><p ref="thisP">{{name}}</p>
</div>
<script>var vm = new Vue({data:{name:'Tom'}}).$mount("#app")console.log(vm.$refs.thisP.textContent);
</script>
</body>
</html>

上面这个例子可以获取P标签中的文本信息。这样就不需要给P标签设一个id,再document.getElementById('xx),相当麻烦。

3.3 $nextTick()

<script>var vm = new Vue({data:{name:'Tom'}}).$mount("#app")vm.name='Jerry';console.log(vm.$refs.thisP.textContent); // Tomvm.$nextTick(function () {console.log(vm.$refs.thisP.textContent); // Jerry})
</script>

当你打印console.log(vm.$refs.thisP.textContent);时,此时标签的文本内容还是’Tom’。()

但我想获取Dom更新的数据啊,我想获取到的是’Jerry’。怎么办?

使用Vue.nextTick()在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM.

this.$nextTick(()  => {console.log(vm.$refs.thisP.textContent);
})

4.EventBus ($emit / $on)

适用于隔代组件通信

eventBus 又称为事件总线,在vue中可以使用它来作为沟通桥梁的概念, 就像是所有组件共用相同的事件中心,可以向该中心注册发送事件或接收事件, 所以组件都可以通知其他组件。

eventBus也有不方便之处, 当项目较大,就容易造成难以维护的灾难

在Vue的项目中怎么使用eventBus来实现组件之间的数据通信呢?具体通过下面几个步骤

4.1 初始化

首先需要创建一个事件总线并将其导出, 以便其他模块可以使用或者监听它.

  // event-bus.js​import Vue from 'vue'export const EventBus = new Vue()

4.2 发送事件

假设你有两个组件: additionNum 和 showNum, 这两个组件可以是兄弟组件也可以是父子组件;这里我们以兄弟组件为例:

<template><div><show-num-com></show-num-com><addition-num-com></addition-num-com></div></template><script>import showNumCom from './showNum.vue'import additionNumCom from './additionNum.vue'export default {components: { showNumCom, additionNumCom }}</script>// addtionNum.vue 中发送事件<template><div><button @click="additionHandle">+加法器</button>    </div></template><script>import {EventBus} from './event-bus.js'console.log(EventBus)export default {data(){return{num:1}},methods:{additionHandle(){EventBus.$emit('addition', {num:this.num++})}}}</script>

4.3 接收事件

// showNum.vue 中接收事件<template><div>计算和: {{count}}</div></template><script>import { EventBus } from './event-bus.js'export default {data() {return {count: 0}},mounted() {EventBus.$on('addition', param => {this.count = this.count + param.num;})}}</script>

这样就实现了在组件addtionNum.vue中点击相加按钮, 在showNum.vue中利用传递来的 num 展示求和的结果.

4.4 移除事件监听者

如果想移除事件的监听, 可以像下面这样操作:

 import { eventBus } from 'event-bus.js'EventBus.$off('addition', {})

5. a t t r s / attrs/ attrs/listeners

适用于隔代组件通信

a t t r s :包含了父作用域中不被 p r o p 所识别 ( 且获取 ) 的特性绑定 ( c l a s s 和 s t y l e 除外 ) 。当一个组件没有声明任何 p r o p 时,这里会包含所有父作用域的绑定 ( c l a s s 和 s t y l e 除外 ) ,并且可以通过 v − b i n d = " attrs:包含了父作用域中不被 prop 所识别 (且获取) 的特性绑定 ( class 和 style 除外 )。当一个组件没有声明任何 prop 时,这里会包含所有父作用域的绑定 ( class 和 style 除外 ),并且可以通过 v-bind=" attrs:包含了父作用域中不被prop所识别(且获取)的特性绑定(classstyle除外)。当一个组件没有声明任何prop时,这里会包含所有父作用域的绑定(classstyle除外),并且可以通过vbind="attrs" 传入内部组件。通常配合 inheritAttrs 选项一起使用。
l i s t e n e r s :包含了父作用域中的 ( 不含 . n a t i v e 修饰器的 ) v − o n 事件监听器。它可以通过 v − o n = " listeners:包含了父作用域中的 (不含 .native 修饰器的) v-on 事件监听器。它可以通过 v-on=" listeners:包含了父作用域中的(不含.native修饰器的)von事件监听器。它可以通过von="listeners" 传入内部组件。

接下来看一个跨级通信的例子:

 // app.vue// index.vue<template><div><child-com1:name="name":age="age":gender="gender":height="height"title="hello"></child-com1></div></template><script>const childCom1 = () => import("./childCom1.vue");export default {components: { childCom1 },data() {return {name: "zhangsan",age: "18",gender: "女",height: "158"};}};</script>// childCom1.vue<template class="border"><div><p>name: {{ name}}</p><p>childCom1的$attrs: {{ $attrs }}</p><child-com2 v-bind="$attrs"></child-com2></div></template><script>const childCom2 = () => import("./childCom2.vue");export default {components: {childCom2},inheritAttrs: false, // 可以关闭自动挂载到组件根元素上的没有在props声明的属性props: {name: String // name作为props属性绑定},created() {console.log(this.$attrs);// { "age": "18", "gender": "女", "height": "158", "title": "hello" }}};</script>// childCom2.vue<template><div class="border"><p>age: {{ age}}</p><p>childCom2: {{ $attrs }}</p></div></template><script>export default {inheritAttrs: false,props: {age: String},created() {console.log(this.$attrs); // { "gender": "女", "height": "158", "title": "hello" }}};</script>

6.provide / inject

适用于隔代组件通信

祖先组件中通过 provider 来提供变量,然后在子孙组件中通过 inject 来注入变量。

provide / inject API 主要解决了跨级组件间的通信问题,不过它的使用场景,主要是子组件获取上级组件的状态,跨级组件间建立了一种主动提供与依赖注入的关系。

注意: 这里不论子组件嵌套有多深, 只要调用了inject 那么就可以注入provide中的数据,而不局限于只能从当前父组件的props属性中回去数据

举例验证

接下来就用一个例子来验证上面的描述: 假设有三个组件: A.vue、B.vue、C.vue 其中 C是B的子组件,B是A的子组件。

// A.vue<template><div><comB></comB></div></template><script>import comB from './comB.vue'export default {name: "A",provide: {for: "demo"},components:{comB}}</script>// B.vue<template><div>{{demo}}<comC></comC></div></template><script>import comC from './comC.vue'export default {name: "B",inject: ['for'],data() {return {demo: this.for}},components: {comC}}</script>// C.vue<template><div>{{demo}}</div></template><script>export default {name: "C",inject: ['for'],data() {return {demo: this.for}}}</script>

7.Vuex

适用于父子、隔代、兄弟组件通信

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。每一个 Vuex 应用的核心就是 store(仓库)。“store” 基本上就是一个容器,它包含着你的应用中大部分的状态 ( state )。

7.1 Vuex 的状态存储是响应式的

当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新。

改变 store 中的状态的唯一途径就是显式地提交 (commit) mutation。这样使得我们可以方便地跟踪每一个状态的变化。

7.2 Vuex模块简介

state:用于数据的存储,是store中的唯一数据源
getters:如vue中的计算属性一样,基于state数据的二次包装,常用于数据的筛选和多个数据的相关性计算
mutations:类似函数,改变state数据的唯一途径,且不能用于处理异步事件
actions:类似于mutation,用于提交mutation来改变状态,而不直接变更状态,可以包含任意异步操作
modules:类似于命名空间,用于项目中将各个模块的状态分开定义和操作,便于维护

8. localStorage或者sessionStorage

这种通信比较简单,缺点是数据和状态比较混乱,不太容易维护。

通过window.localStorage.getItem(key)获取数据
通过window.localStorage.setItem(key,value)存储数据

注意用JSON.parse()和JSON.stringify() 做数据格式转换, localStorage或者sessionStorage可以结合vuex, 实现数据的持久保存,同时使用vuex解决数据和状态混乱问题。

9.slot

把子组件的数据通过插槽的方式传给父组件使用,然后再插回来。

// Child.vue
<template><div><slot :user="user"></slot></div>
</template>
export default{data(){return {user:{ name:"xxx" }}}
}// Parent.vue
<template><div><child v-slot="slotProps">{{ slotProps.user.name }}</child></div>
</template>

总结

常见使用场景可以分为三类:

父子组件通信: props/ e m i t 、 emit、 emitparent/ c h i l d r e n 、 p r o v i d e / i n j e c t 、 r e f / children、 provide/inject 、 ref/ childrenprovide/injectref/refs 、 a t t r s / attrs/ attrs/listeners、slot
兄弟组件通信: eventBus 、 Vuex
祖孙组件通信: eventBus、 Vuex、 provide / inject 、 $attrs / $listeners

写在最后

✨ 原创不易,希望各位大佬多多支持。

👍 点赞,你的认可是我创作的动力。

⭐️ 收藏,感谢你对本文的喜欢。

✏️ 评论,你的反馈是我进步的财富。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/42297.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

三国鼎立:ChatGPT、百度文心一言、微软 New Bing

推荐国内可访问chatGPT: chatGTP --------------------------------------------------------------------------------------------------------------- ChatGTP&#xff1a;更像是三国中魏国&#xff0c;地大物博用户多。 百度文心一言&#xff1a;更像是三国中的蜀国&…

在Mac中设置Ctrl+C/V进行复制/粘贴

在win环境转到mac环境,感觉最大的就是这个⌘键了,看了很多帖子感觉都是片面的 进行系统偏好设置 > 键盘 > 快捷键 > App快捷键点击如图加号 这一步很重要,比如你要修改访达的复制粘贴,那就代打开访达 根据访达的编辑一栏自定义修改 菜单标题就是 全选 键盘快捷键自…

如何在Mac上复制和粘贴

如果您是具有Windows PC背景的新Mac用户&#xff0c;则可能想知道如何在macOS中使用典型的复制和粘贴命令。 在Windows中&#xff0c;“复制”和“粘贴”键组合分别为Control-C和Control-V。在Mac上&#xff0c;这非常相似–您要做的就是使用Command&#xff08;⌘&#xff09;…

mac截图复制到剪贴板_如何一次将多个内容复制到Mac的剪贴板中

mac截图复制到剪贴板 You know that thing where you copy something important, forget to paste it anywhere, then copy something else? It sucks, because the important thing you copied first is gone. 您知道要复制重要内容的东西&#xff0c;忘记将其粘贴到任何地方…

Mac复制改为拷贝

在默认情况下&#xff0c;mac电脑的复制为复制粘贴&#xff0c;即会生成一个副本文件&#xff0c;并没有达到Win下复制功效。 不知你是否遇到过&#xff0c;下面贴图介绍如何调整为真正的复制功能。 1.打开 系统偏好设置 2.选择 键盘 3.快捷键-App快捷键 然后删除 复制 快捷键…

Mac mini 使用普通键盘设置 Windows 的粘贴、复制、剪切习惯

问题描述 通常我们会习惯性用左手小拇指按最左下角的 ctrl 键作为功能前缀键&#xff0c;进行复制、粘贴、剪切等操作&#xff0c;但将普通键盘接到 macOS 设备上&#xff0c;会将 windows 徽标键视为 command 键&#xff0c;此时习惯了 Windows 系统的朋友进行复制、粘贴、剪…

mac item2 复制会话session

按照如下图红框内设置 Command中输入ssh 常登陆的ip&#xff08;如果不配置这一步则复制session时还要自己输入ssh命令&#xff0c;只是不需要输入密码而已&#xff09; 在自己的mac终端, vim ~/.ssh/config 添加 host *ControlMaster autoControlPath ~/.ssh/master-%r%h:…

WindowsMac剪贴板如何存储多条复制记录

Windows版 1.第一步点击电脑左下方“开始菜单”按钮。 2..点击 “设置”按钮。 3.打开设置之后点击"系统"。 4.然后下拉找到“剪贴板”。 5.选中剪贴板&#xff0c;然后在右侧即可开启剪贴板历史记录功能。 按“WindowsV”组合键键即可打开剪贴板。复制或者剪切过的…

五个最好的复制/粘贴的Mac App应用

如果你刚用Mac&#xff0c;之前是用Windows电脑的&#xff0c;第一个问题就会发现&#xff0c;Mac上的复制/粘贴找不到了。如果你也有同样的问题&#xff0c;或者你在找Mac上有没有好用的剪贴板管理工具&#xff0c;可以在下面的文章中找到答案。 Mac上怎样优雅的复制/粘贴 c…

Mac简单易用的复制软件——“TouchCopy”

TouchCopy是Mac平台上一款简单易用的复制软件&#xff0c;可以轻松的将你的照片、视频、通讯录、文档、日历复制到pc端或者是磁盘里。有需要的朋友欢迎前来macdown下载体验&#xff01; 功能 1、将音乐从iPhone / iPod / iPad传输到iTunes将音乐从iPod或iOS设备复制到PC或Mac硬…

苹果Mac电脑的复制粘贴不能用了

复制 (⌘ C) 和粘贴 (⌘ V) 是使用Mac电脑过程中遇到频率非常高的快捷组合键&#xff0c;突然你发现它们不能使用了&#xff0c;会非常崩溃。macw小编今天为大家带来详细解决办法&#xff0c;让您的复制粘贴重新启用起来&#xff01; 为什么 Mac 剪贴板不起作用 我们在 Mac…

Mac下iterm2 克隆会话功能

因为每次需要先登录跳转机&#xff0c;再登录开发机&#xff0c;输入两次密码&#xff0c;过于繁琐&#xff0c;所以上网找了iterm下克隆会话功能。 网上说command下的command也要配置&#xff0c;亲测不用&#xff0c;只选中下面的reuse previous sessions’s directory就行。…

花启宝是什么软件,来聊一聊“花启宝”的详情

很多人在问我&#xff0c;你在做的软件是什么&#xff1f;我本人也就是通过它慢慢学习成长起来的。还是一个网友推荐的&#xff0c;现在他对我来说算是大佬了&#xff0c;已经单飞了&#xff0c;好久都没有联系了&#xff0c;呵呵&#xff0c;真是人往高处走&#xff0c;水往低…

chatgpt赋能python:Python抢商品:自动化实现秒杀购物的利器

Python抢商品&#xff1a;自动化实现秒杀购物的利器 随着互联网和电商的高度融合&#xff0c;电商平台受到越来越多的用户关注和青睐。在线购物已成为人们日常生活中必不可少的一部分&#xff0c;不管是网购小白还是技术大牛&#xff0c;都喜欢在各种平台上刷到想要的商品。但…

chatgpt赋能python:Python自动购买商品的好处、方法及其实现

Python自动购买商品的好处、方法及其实现 越来越多的人通过网购方式购买商品&#xff0c;为了避免购物“抢购”难的烦恼&#xff0c;很多人选择了自动化脚本的方式来帮助他们完成网购。这其中&#xff0c;Python的应用越来越广泛。本文将详细介绍Python自动购买商品的好处、方…

在线AI智能写诗工具

调用了百度智能API,完成了这个在线AI智能写诗工具&#xff0c;可以写首诗送你*朋友 来源:https://www.toolfk.com/tool-online-poem

AI 智能写情诗、藏头诗模型训练

一、AI 智能情诗、藏头诗展示 最近使用PyTorch的LSTM训练一个写情诗&#xff08;七言&#xff09;的模型&#xff0c;可以随机生成情诗、也可以生成藏头情诗。 在特殊的日子用AI生成一首这样的诗&#xff0c;是不是很酷&#x1f60e;&#x1f498;&#xff01;下面分享下AI 智…

OpenAI新作Shap-e算法使用教程

一、知识点 Shap-e是基于nerf的开源生成3d模型方案。它是由如今热火朝天的Open AI公司&#xff08;chatgpt&#xff0c;Dell-E2&#xff09;开发、开源的。Shap-e生成的速度非常快&#xff0c;输入关键词即可生成简单模型&#xff08;限于简单单体模型&#xff09;。 二、环境…

游戏策划

游戏策划:注意人员安排与时间管控等多方面因素 第一次策划&#xff0c;仅供参考 其他同伴们的更多游戏策划

第四天 游戏策划学习

摸鱼了太久&#xff0c;今天来学习下回合制战斗的乱敏机制的作用和本质 首先什么是乱敏&#xff1a; 就是指敌我双方如果在一个速度区间内&#xff0c;并不是按照速度的绝对高低来决定出手顺序&#xff0c;而且有一定的几率&#xff0c;速度慢的角色会比速度快的角色先出手。…