当前位置: 首页 > news >正文

Vue 系列之:组件通讯

子组件调用父组件方法

1、直接在子组件中通过 this.$parent.event 来调用父组件的方法

父组件:

<template><p><child></child></p>
</template>
<script>import child from './child';export default {components: {child},methods: {fatherMethod() {console.log('测试');}}};
</script>

子组件:

<template><p><button @click="childMethod()">点击</button></p>
</template>
<script>export default {methods: {childMethod() {this.$parent.fatherMethod();}}};
</script>

2、父组件使用 v-on 监听事件,子组件使用 $emit 件触发事件

@ 是 v-on 的缩写

父组件:

<template><p><child @method1="fatherMethod"></child></p>
</template>
<script>import child from './child';export default {components: {child},methods: {fatherMethod(params) {console.log('测试', params);}}};
</script>

子组件:

<template><p><button @click="childMethod()">点击</button></p>
</template>
<script>export default {methods: {childMethod() {this.$emit('method1', params); // params 为参数,可不传 // this.$emit('method1');}}};
</script>

3、父组使用 v-bind 绑定事件,子组件用 props 接收事件

: 是 v-bind 的缩写

父组件:

<template><p><child :method1="fatherMethod"></child></p>
</template>
<script>import child from './child';export default {components: {child},methods: {fatherMethod() {console.log('测试');}}};
</script>

子组件:

<template><p><button @click="childMethod()">点击</button></p>
</template>
<script>export default {props: {method1: {type: Function,default: null}},methods: {childMethod() {if (this.method1) {this.method1();}}}};
</script>

父组件调用子组件方法

1、通过 ref 直接调用子组件的方法

父组件:

<template><div><Button @click="fatherMethod">点击调用子组件方法</Button><Child ref="child"/></div>
</template>    <script>
import Child from './child';
export default {methods: {fatherMethod() {this.$refs.child.childMethod();},},
}
</script>

子组件:

<template><div>我是子组件</div>
</template><script>
export default {methods: {childMethod() {console.log('我是子组件的方法');},},
};</script>

2、通过组件的$emit$on方法(可以,但是没必要)

父组件:

<template><div><Button @click="fatherMethod">点击调用子组件方法</Button><Child ref="child"/></div>
</template>    <script>
import Child from './child';
export default {methods: {fatherMethod() {this.$refs.child.$emit("getChildMethod")    //子组件$on中的名字},},
}
</script>

子组件:

<template><div>我是子组件</div>
</template><script>
export default {mounted() {this.$nextTick(function() {this.$on('getChildMethod', this.childMethod);});},methods: {childMethod() {console.log('我是子组件方法');}}
};
</script>

兄弟组件

  • 方法1:通过父组件作为中转

    • 通过 ref 和 $parent

    • 通过 provide 和 inject

  • 方法2:使用 EventBus 事件总线

  • 方法3:vuex,下一篇内容会讲

EventBus 使用方式

1、初始化——全局定义

可以将 eventBus 绑定到 vue 实例的原型上,也可以直接绑定到 window 对象上

//main.js//注册方式一
Vue.prototype.$EventBus = new Vue();//注册方式二
window.EventBus = new Vue();

2、监听事件

//使用方式一
this.$EventBus.$on('eventName', (param1, param2, ...) => {//需要执行的代码
})//使用方式二
EventBus.$on('eventName', (param1, param2, ...) => {//需要执行的代码
})

3、触发事件

//使用方式一
this.$EventBus.$emit('eventName', param1, param2,...)//使用方式二
EventBus.$emit('eventName', param1, param2,...)

4、移除监听事件

为了避免在监听时,事件被反复触发,通常需要在页面销毁时移除事件监听。或者在开发过程中,由于热更新,事件可能会被多次绑定监听,这时也需要移除事件监听。

//使用方式一
this.$EventBus.$off('eventName');//使用方式二
EventBus.$off('eventName');//移除所有
EventBus.$off();

5、示例

简单示例一:

<!--组件 A.vue-->
<script>
export default {  mounted() {  // 监听事件this.$EventBus.$on('custom-event', this.handleEvent)  },  methods: {  handleEvent(data) {  console.log(data)  }  }  
}
</script><!--组件 B.vue-->
<template>  <button @click="handleClick">触发事件</button>  
</template>  <script>
export default {data() {return {str: '我来自 B 组件'}}methods: {handleClick() {// 触发事件this.$EventBus.$emit('custom-event', this.str)  }  }  
}  
</script>

示例二:

假设兄弟组件有三个,分别是 A、B、C 组件,A 组件如何获取 B 或者 C 组件的数据

这时候就可以使用 EventBus。EventBus 是一种发布/订阅模式,用于在组件之间传递事件和数据。A 组件可以监听由 B 或 C 组件发布的事件,并在事件处理函数中获取传递的数据。

思路:
A 组件中使用 Event.$on 监听事件
B、C 组件中使用 Event.$emit 触发事件

// A.vue  
<template>  <div>A 接收到的数据: {{ receivedData }}</div>  
</template>  <script>  export default {  data() {  return {  receivedData: null  };  },  mounted() {  // 监听事件  EventBus.$on('custom-event', (data) => {  this.receivedData = data.message;  });  },  beforeDestroy() {  // 组件销毁前,移除事件监听器  EventBus.$off('custom-event');  }  
};  
</script>
// B.vue 和 C.vue
<template>  <button @click="sendData">发送数据</button>  
</template>  <script>  
export default {  methods: {sendData() {  const data = { message: 'I am from B' };// 触发事件EventBus.$emit('data-from-a', data);  }  }  
};  
</script>

多层组件(爷孙)

provide() 和 inject[]

用于将数据或方法暴露给组件树中的任何后代组件,哪怕是深层次的后代组件都可以访问到这些数据,而无需通过 props 层层传递。

注意:provide 和 inject 主要用于单向数据传递,即从祖先组件流向后代组件。虽然可以在后代组件中修改注入的数据,但这种做法会破坏单向数据流的原则,导致数据流向不清晰,难以调试,因此不建议这样做。

Vue2 用法:

<!--爷/父 组件-->
<template><div id="app"><Children></Children></div>
</template><script>
import Children from "./Children.vue";
export default {name: 'parent',components: { Children },provide() {return {parentEvent: this.myEvent,parentData: this.message,parentStr: '字符串数据'};},data() {return {message: 'data中的数据'}},methods: {myEvent(params1, params2) {console.log(params1, params2)},}
};
</script>
<!--子/孙 组件-->
<template><el-button @click="handleClick">测试</el-button>
</template><script>
export default {name: 'child',inject: ["parentEvent", "parentData", "parentStr"],methods: {handleClick() {this.parentEvent('参数1', '参数2');console.log(this.parentData)console.log(this.parentStr)}}
};
</script>

从上到下依次打印:

参数1 参数2
data中的数据
字符串数据

Vue3 用法:

<!--爷/父 组件-->
<template><div id="app"><Children></Children></div>
</template><script setup>
import { ref, provide } from "vue";
import Children from "./Children.vue";
const message = ref('data中的数据');
const str = '字符串数据'
function myEvent(params1, params2) {console.log(params1, params2)
}
provide('parentEvent', myEvent);
provide('parentData', message);
provide('parentStr', str);
</script>
<!--子/孙 组件-->
<template><el-button @click="handleClick">测试</el-button>
</template><script setup>
import { inject } from "vue";
const parentEvent = inject('parentEvent');
const parentData = inject('parentData');
const parentStr = inject('parentStr', '默认值');function handleClick() {parentEvent('参数1', '参数2')console.log(parentData.value)console.log(parentStr)
}
</script>

细心的朋友已经发现:在 Vue3 中,子组件打印的是 parentData.value,这说明 parentData 是一个响应式对象。

直接总结:

特性Vue2Vue3
响应式支持provide 提供的数据不是响应式provide 提供的数据是响应式
默认值支持不支持默认值支持默认值,inject 的第二个参数就是默认值

$attrs 和 $listeners

$attrs

$attrs 是一个对象,包含了父组件传递给子组件的所有非 prop 属性(即没有在 props 中定义的属性)。

当你希望将父组件传递的属性传递给子组件的子组件时,可以使用 $attrs。

父组件:

<!-- 父组件 -->
<template><div id="app"><Children :params1="params1" :params2="params2" /></div>
</template><script>
import Children from "./Children.vue";
export default {name: 'parent',components: { Children },data() {return {params1: '测试1',params2: '测试2',params3: '测试3',}},mounted() {setTimeout(() => {this.params2 += 'timeout'}, 5000);},
};
</script>

子组件:

<!-- 子组件 -->
<template><div><p>params1: {{ $attrs.params1 }}</p><p>params2: {{ $attrs.params2 }}</p><p>params3: {{ $attrs.params3 }}</p><Groundson v-bind="$attrs" :params4="params4"/></div>
</template><script>
import Groundson from "./Groundson.vue";
export default {name: 'children',components: { Groundson },props: {params1: {type: String,default: ""}},data() {return {params4: '测试4'}},mounted() {console.log("children $attrs:", this.$attrs);},
};
</script>

孙组件:

<!-- 孙组件 -->
<template><div></div>
</template>
<script>export default {name: 'groundson',mounted() {console.log("groundson $attrs:", this.$attrs);},
};
</script>

页面:

在这里插入图片描述

打印:

在这里插入图片描述
总结:

  • 没有通过 v-bind 传递给子组件的,子组件的 $attrs 中不会有该属性

  • 通过 v-bind 传递给了子组件,但是子组件使用了 props 接收的,子组件的 $attrs 中不会有该属性

  • $attrs 中的属性值是响应式的

  • 在子组件中使用 v-bind=“$attrs” 可以将子组件的 $attrs 中的所有属性都传递给孙子组件,孙子组件也是按同样的规则接收

inheritAttrs 的作用:

观察页面元素发现:

在这里插入图片描述
子组件的根元素和孙子组件的根元素都多了一些属性

官方解释:默认情况下,父组件传递的,但没有被子组件解析为 props 的 attributes 绑定会被“透传”。这意味着当我们有一个单根节点的子组件时,这些绑定会被作为一个常规的 HTML attribute 应用在子组件的根节点元素上。我们可以通过设置 inheritAttrs 为 false 来禁用这个默认行为。

例如在子组件中加上 inheritAttrs: false

在这里插入图片描述
子组件根节点的属性消失了,由于没有在孙子组件中设置,孙子组件的根节点还保留着属性

$listeners

$listeners 包含了父组件传递给子组件的所有事件监听器(即 v-on 绑定的事件)。

与 $attrs 类似, $attrs 是传递属性, $listeners 是传递方法。这里就不再举例了。

注意:在 Vue3 中,$listeners 已经被移除,其功能被合并到了 $attrs 中。

相关文章:

Vue 系列之:组件通讯

子组件调用父组件方法 1、直接在子组件中通过 this.$parent.event 来调用父组件的方法 父组件&#xff1a; <template><p><child></child></p> </template> <script>import child from ./child;export default {components: {chi…...

【Linux实践系列】:用c语言实现一个shell外壳程序

&#x1f525;本文专栏&#xff1a;Linux Linux实践项目 &#x1f338;博主主页&#xff1a;努力努力再努力wz 那么今天我们就要进入Linux的实践环节&#xff0c;那么我们之前学习了进程控制相关的几个知识点&#xff0c;比如进程的终止以及进程的等待和进程的替换&#xff0c;…...

STL map 的 lower_bound(x)、upper_bound(x) 等常用函数

【STL map 简介】 ● STL map 是一种关联容器&#xff0c;存储键值对&#xff0c;每个键&#xff08;key value&#xff09;是唯一的&#xff0c;而值&#xff08;mapped value&#xff09;可以重复。构建 STL map 时&#xff0c;无论元素插入顺序如何&#xff0c;STL map 中的…...

【A2DP】SBC 编解码器互操作性要求详解

目录 一、SBC编解码器互操作性概述 二、编解码器特定信息元素(Codec Specific Information Elements) 2.1 采样频率(Sampling Frequency) 2.2 声道模式(Channel Mode) 2.3 块长度(Block Length) 2.4 子带数量(Subbands) 2.5 分配方法(Allocation Method) 2…...

Computational Linguistics期刊全解析:领域顶刊的投稿指南与学术价值

在人工智能与语言学交叉融合的浪潮中&#xff0c;《Computational Linguistics》&#xff08;CL&#xff09;作为该领域的标杆期刊&#xff0c;始终是研究者发表前沿成果的首选平台。本文将从期刊影响力、投稿策略、收稿方向等角度&#xff0c;为学者提供一份全面的指南。 一、…...

【量化科普】Sharpe Ratio,夏普比率

【量化科普】Sharpe Ratio&#xff0c;夏普比率 &#x1f680;量化软件开通 &#x1f680;量化实战教程 在量化投资领域&#xff0c;夏普比率&#xff08;Sharpe Ratio&#xff09;是一个非常重要的风险调整后收益指标。它由诺贝尔经济学奖得主威廉F夏普&#xff08;William…...

运行OpenManus项目(使用Conda)

部署本项目需要具备一定的基础&#xff1a;Linux基础、需要安装好Anaconda/Miniforge&#xff08;Python可以不装好&#xff0c;直接新建虚拟环境的时候装好即可&#xff09;&#xff0c;如果不装Anaconda或者Miniforge&#xff0c;只装过Python&#xff0c;需要确保Python是3.…...

TikTok Shop欧洲市场爆发,欧洲TikTok 运营网络专线成运营关键

TikTok在欧洲的影响力还在持续攀升&#xff0c;日前&#xff0c;TikTok发布了最新的欧盟执行和使用数据报告&#xff0c;报告中提到&#xff1a; 2024年7~12月期间&#xff0c;TikTok在欧盟地区的月活用户达1.591亿&#xff0c;较上一报告期&#xff08;2024年10月发布&#xf…...

基于YOLO11深度学习的电瓶车进电梯检测与语音提示系统【python源码+Pyqt5界面+数据集+训练代码】

《------往期经典推荐------》 一、AI应用软件开发实战专栏【链接】 项目名称项目名称1.【人脸识别与管理系统开发】2.【车牌识别与自动收费管理系统开发】3.【手势识别系统开发】4.【人脸面部活体检测系统开发】5.【图片风格快速迁移软件开发】6.【人脸表表情识别系统】7.【…...

计算机毕业设计SpringBoot+Vue.js制造装备物联及生产管理ERP系统(源码+文档+PPT+讲解)

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…...

微服务保护:Sentinel

home | Sentinelhttps://sentinelguard.io/zh-cn/ 微服务保护的方案有很多&#xff0c;比如&#xff1a; 请求限流 线程隔离 服务熔断 服务故障最重要原因&#xff0c;就是并发太高&#xff01;解决了这个问题&#xff0c;就能避免大部分故障。当然&#xff0c;接口的并发…...

labelimg标注的xml标签转换为yolo格式标签

本文不生产技术&#xff0c;只做技术的搬运工&#xff01;&#xff01;&#xff01; 前言 在yolo训练时&#xff0c;我们需要对图像进行标注&#xff0c;而使用labelimg标注时如果直接选择输出yolo格式的数据集&#xff0c;则原始数据的很多信息无法被保存&#xff0c;因此一版…...

VUE3开发-9、axios前后端跨域问题解决方案

VUE前端解决跨域问题 前端页面需要改写 如果无效&#xff0c;记得重启服务器 后端c#解决跨域问题 前端js取值&#xff0c;后端c#跨域_c# js跨域-CSDN博客...

机试准备第12天

首先学习队列&#xff0c;队列有先进先出的特性。广度优先遍历需要基于队列实现&#xff0c;C中的stl引入了队列的实现方式。队列支持push()&#xff0c;进入队尾&#xff0c;pop()出队&#xff0c;队头出队&#xff0c;front()获取队首元素&#xff0c;back()获取队尾元素&…...

计算机二级MS之PPT

声明&#xff1a;跟着大猫和小黑学习随便记下一些笔记供大家参考&#xff0c;二级考试之前将持续更新&#xff0c;希望大家二级都能轻轻松松过啦&#xff0c;过了二级的大神也可以在评论区留言给点建议&#xff0c;感谢大家&#xff01;&#xff01; 文章目录 考题难点1cm25px…...

伊藤积分(Ito Integral):随机世界中的积分魔法

伊藤积分&#xff08;Ito Integral&#xff09;&#xff1a;随机世界中的积分魔法 在研究随机微分方程&#xff08;SDE&#xff09;和布朗运动时&#xff0c;伊藤积分&#xff08;Ito Integral&#xff09;是一个绕不开的关键概念。它是处理布朗运动随机项 ( d W ( t ) dW(t)…...

【Deepseek应用】Zotero+Deepseek 阅读和分析文献(下)

【Deepseek应用】Deepseek R1 本地部署&#xff08;OllamaDockerOpenWebUI&#xff09; 【Deepseek应用】ZoteroDeepseek 阅读和分析文献&#xff08;上&#xff09; 【Deepseek应用】ZoteroDeepseek 阅读和分析文献&#xff08;下&#xff09; 使用邀请码 cXfb9wOT 注册 硅基流…...

人工智能与深度学习的应用案例:从技术原理到实践创新

第一章 引言 人工智能(AI)作为21世纪最具变革性的技术之一,正通过深度学习(Deep Learning)等核心技术推动各行业的智能化进程。从计算机视觉到自然语言处理,从医疗诊断到工业制造,深度学习通过模拟人脑神经网络的层次化学习机制,实现了对复杂数据的高效分析与决策。本…...

Docker和DockerCompose基础教程及安装教程

Docker的应用场景 Web 应用的自动化打包和发布。自动化测试和持续集成、发布。在服务型环境中部署和调整数据库或其他的后台应用。从头编译或者扩展现有的 OpenShift 或 Cloud Foundry 平台来搭建自己的 PaaS 环境。 CentOS Docker 安装 使用官方安装脚本自动安装 安装命令…...

ArcGIS操作:13 生成最小外接矩阵

应用情景&#xff1a;筛选出屋面是否能放下12*60m的长方形&#xff0c;作为起降场候选点&#xff08;一个不规则的形状内&#xff0c;判断是否能放下指定长宽的长方形&#xff09; 1、面积初步筛选 Area ≥ 720 ㎡ 面积计算见 2、打开 ArcToolbox → Data Management Tools …...

Java 语言特性(面试系列2)

一、SQL 基础 1. 复杂查询 &#xff08;1&#xff09;连接查询&#xff08;JOIN&#xff09; 内连接&#xff08;INNER JOIN&#xff09;&#xff1a;返回两表匹配的记录。 SELECT e.name, d.dept_name FROM employees e INNER JOIN departments d ON e.dept_id d.dept_id; 左…...

云原生核心技术 (7/12): K8s 核心概念白话解读(上):Pod 和 Deployment 究竟是什么?

大家好&#xff0c;欢迎来到《云原生核心技术》系列的第七篇&#xff01; 在上一篇&#xff0c;我们成功地使用 Minikube 或 kind 在自己的电脑上搭建起了一个迷你但功能完备的 Kubernetes 集群。现在&#xff0c;我们就像一个拥有了一块崭新数字土地的农场主&#xff0c;是时…...

突破不可导策略的训练难题:零阶优化与强化学习的深度嵌合

强化学习&#xff08;Reinforcement Learning, RL&#xff09;是工业领域智能控制的重要方法。它的基本原理是将最优控制问题建模为马尔可夫决策过程&#xff0c;然后使用强化学习的Actor-Critic机制&#xff08;中文译作“知行互动”机制&#xff09;&#xff0c;逐步迭代求解…...

centos 7 部署awstats 网站访问检测

一、基础环境准备&#xff08;两种安装方式都要做&#xff09; bash # 安装必要依赖 yum install -y httpd perl mod_perl perl-Time-HiRes perl-DateTime systemctl enable httpd # 设置 Apache 开机自启 systemctl start httpd # 启动 Apache二、安装 AWStats&#xff0…...

《从零掌握MIPI CSI-2: 协议精解与FPGA摄像头开发实战》-- CSI-2 协议详细解析 (一)

CSI-2 协议详细解析 (一&#xff09; 1. CSI-2层定义&#xff08;CSI-2 Layer Definitions&#xff09; 分层结构 &#xff1a;CSI-2协议分为6层&#xff1a; 物理层&#xff08;PHY Layer&#xff09; &#xff1a; 定义电气特性、时钟机制和传输介质&#xff08;导线&#…...

今日学习:Spring线程池|并发修改异常|链路丢失|登录续期|VIP过期策略|数值类缓存

文章目录 优雅版线程池ThreadPoolTaskExecutor和ThreadPoolTaskExecutor的装饰器并发修改异常并发修改异常简介实现机制设计原因及意义 使用线程池造成的链路丢失问题线程池导致的链路丢失问题发生原因 常见解决方法更好的解决方法设计精妙之处 登录续期登录续期常见实现方式特…...

Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信

文章目录 Linux C语言网络编程详细入门教程&#xff1a;如何一步步实现TCP服务端与客户端通信前言一、网络通信基础概念二、服务端与客户端的完整流程图解三、每一步的详细讲解和代码示例1. 创建Socket&#xff08;服务端和客户端都要&#xff09;2. 绑定本地地址和端口&#x…...

如何更改默认 Crontab 编辑器 ?

在 Linux 领域中&#xff0c;crontab 是您可能经常遇到的一个术语。这个实用程序在类 unix 操作系统上可用&#xff0c;用于调度在预定义时间和间隔自动执行的任务。这对管理员和高级用户非常有益&#xff0c;允许他们自动执行各种系统任务。 编辑 Crontab 文件通常使用文本编…...

NPOI操作EXCEL文件 ——CAD C# 二次开发

缺点:dll.版本容易加载错误。CAD加载插件时&#xff0c;没有加载所有类库。插件运行过程中用到某个类库&#xff0c;会从CAD的安装目录找&#xff0c;找不到就报错了。 【方案2】让CAD在加载过程中把类库加载到内存 【方案3】是发现缺少了哪个库&#xff0c;就用插件程序加载进…...

关于easyexcel动态下拉选问题处理

前些日子突然碰到一个问题&#xff0c;说是客户的导入文件模版想支持部分导入内容的下拉选&#xff0c;于是我就找了easyexcel官网寻找解决方案&#xff0c;并没有找到合适的方案&#xff0c;没办法只能自己动手并分享出来&#xff0c;针对Java生成Excel下拉菜单时因选项过多导…...