组件通信八种方式(vue3)

news2024/11/25 12:31:09

一、父传子(props)

关于Props的相关内容可以参考:Props-CSDN博客

父组件通过 props 向子组件传递数据。适合简单的单向数据流。

<!-- Parent.vue -->
<template>
  <Child :message="parentMessage" />
</template>

<script setup>
const parentMessage = ref('Hello')
</script>
  • 在父组件中,通过 :message 语法将 parentMessage 传递给子组件 Child。
<!-- Child.vue -->
<template>
  <div>{{ props.message }}</div>
</template>

<script setup>
import { defineProps } from 'vue';
const props = defineProps({
      message: {
        type: String,
        required: true // 指定该 prop 为必需
      }
    });
</script>
  • 在子组件 Child 中,使用 props 选项定义接收的 message 属性
  • type 用于指定 props 的类型(如 String、Number 等)
  • required 用于指示该 prop 是否为必需

二、子传父(自定义事件)

子组件可以通过 $emit 向父组件发送事件,父组件通过v-on监听这些事件来接收数据

<!-- 绑定自定义事件xxx:实现子组件给父组件传递数据 -->
<Event2 @xxx="handler3"></Event2>    //handler3是一个你想操作的方法
  • 父组件中接收自定义事件
<button @click="sendMessage">点击触发子传父</button>

let $emit = defineEmits(['xxx']);   //利用defineEmits方法返回函数触发自定义事件
sendMessage() {
      $emit('childMessage', 'Hello from Child!');
}
  • 子组件中:点击按钮触发“向父组件传递信息”的操作

三、v-model组件通信(父子组件数据同步)

vue3.4之前:

1、前言:通过 v-model,父组件可以将数据传递给子组件,子组件可以在内部修改这些数据,并将更新后的值同步回父组件

2、使用 v-model 实现数据同步的步骤:

  • 父组件传递数据:父组件使用 v-model 将数据传递给子组件。
  • 子组件定义 modelValue:子组件需要定义 modelValue 属性来接收来自父组件的数据。
  • 子组件触发更新:子组件通过 $emit 触发 update:modelValue 事件,将修改后的数据发送回父组件。

3、代码示范:

//父组件中
<Child v-model:value="value" />
//子组件中
<template>
    <input v-model="inputValue" @input="updateValue" />  //@input 是一个原生 DOM 事件,表示用户在输入框中输入内容时触发的事件。
</template>

<script setup lang="ts">
import { defineProps, defineEmits, ref, watch } from 'vue';

// 定义 props,并接收父组件传递的值
const props = defineProps<{
  modelValue: string; 
}>();

// 定义事件
const emit = defineEmits<{
  (e: 'update:modelValue', value: string): void; 
}>();

// 创建响应式变量
const inputValue = ref(props.modelValue); 

// 监听 props 的变化,确保 inputValue 始终与 modelValue 同步
watch(
  () => props.modelValue,
  (newValue) => {
    inputValue.value = newValue;
  }
);

// 更新值并触发更新事件
const updateValue = () => {
  emit('update:modelValue', inputValue.value);
};
</script>

注:其主要实现原理还是利用了props和自定义事件的组合使用,v-model只是帮我们同步了数据和方法

vue3.4之后(使用 defineModel())

1、defineModel():

该函数简化了 v-model 的使用,自动处理 modelValue 的接收和 update:modelValue 事件的发出。

2、使用:

<!-- Parent.vue -->
<Child v-model="countModel" />
  • 在父组件中,使用 v-model 将 countModel 绑定到子组件 Child 的 model(这是 defineModel() 中定义的)。
  • 当父组件的 countModel 变化时,子组件将自动接收到更新。
<!-- Child.vue -->
<script setup>
const model = defineModel()

function update() {
  model.value++
}
</script>

<template>
  <div>Parent bound v-model is: {{ model }}</div>
  <button @click="update">Increment</button>
</template>
  • defineModel() 函数用于定义 v-model 的数据绑定。在这里,它会自动接收来自父组件的 countModel 的值,并将其存储在 model 中。
  • model 变量是响应式的,因此,当父组件的 countModel 发生变化时,model 也会更新。

3、数据流动

从父组件到子组件:父组件的 countModel 值通过 v-model 传递给子组件,并被 defineModel() 接收并存储在 model 中。

从子组件到父组件:

  • 当用户在子组件中点击按钮,update() 方法会增加 model.value 的值。
  • -由于 defineModel() 自动处理了 update:modelValue 事件,这样子组件在更新 model.value 时,会自动触发父组件 countModel 的更新。

4、v-model的参数

组件上的v-model也可以接受一个参数:

<MyComponent v-model:title="bookTitle" />

在子组件中,通过将字符串作为第一个参数传递给defineModel()来支持相应的参数:

<!-- MyComponent.vue -->
<script setup>
const title = defineModel('title')
</script>

<template>
  <input type="text" v-model="title" />
</template>

5、多个v-model绑定

组件上的每一个v-model都会同步不同的prop,而无需额外的选项:

 <UserName
  v-model:first-name="first"
  v-model:last-name="last"
/>
<!-- Username.vue -->
<script setup>
const firstName = defineModel('firstName')
const lastName = defineModel('lastName')
</script>

<template>
  <input type="text" v-model="firstName" />
  <input type="text" v-model="lastName" />
</template>

6、处理 v-model 修饰符

想创建一个自定义的修饰符来实现某种功能,例:将 v-model 绑定输入的字符串值第一个字母转为大写

<MyComponent v-model.capitalize="myText" />

为了能够基于修饰符选择性地调节值的读取和写入方式,我们可以给 defineModel() 传入 get 和 set 这两个选项。

<script setup>
const [model, modifiers] = defineModel({
  set(value) {
    if (modifiers.capitalize) {
      return value.charAt(0).toUpperCase() + value.slice(1)
    }
    return value
  }
})
</script>

<template>
  <input type="text" v-model="model" />
</template>

7、带参数的v-model修饰符

这里用例子展示了如何在使用多个不同参数的v-model时使用修饰符:

<UserName
  v-model:first-name.capitalize="first"
  v-model:last-name.uppercase="last"
/>
<script setup>
const [firstName, firstNameModifiers] = defineModel('firstName')
const [lastName, lastNameModifiers] = defineModel('lastName')

console.log(firstNameModifiers) // { capitalize: true }
console.log(lastNameModifiers) // { uppercase: true }
</script>

总结

Vue 3.4 后,使用 v-model 进行组件通信的方式更加简洁和高效,提升了代码的可读性和维护性。

四、全局事件总线(mitt)

背景:在 Vue 3 中,虽然不再推荐使用全局事件总线(Event Bus)作为组件之间通信的主要方式,但仍然可以通过一些方法实现类似的功能。全局事件总线的主要目的是在不同组件之间传递事件,而不通过父子组件的直接通信。

使用:

1、安装 mitt:

mitt 是一个轻量级的事件总线库,可以方便地在 Vue 3 中使用。

npm install mitt
2、创建事件总线:
// eventBus.js
import mitt from 'mitt';

const eventBus = mitt();

export default eventBus;
3、在组件中使用事件总线:
<!-- ComponentA.vue -->


<script setup lang="ts">
import eventBus from './eventBus';

const sendMessage = () => {
  eventBus.emit('xxx', 'Hello from Component A!');
};
</script>
<!-- ComponentB.vue -->

<script setup lang="ts">
import {onMounted, onUnmounted } from 'vue';
import eventBus from './eventBus';


const receiveMessage = (msg: string) => {
  message.value = msg;
};

 //在事件总线中注册一个事件监听器,以便在特定事件发生时执行相应的回调函数
onMounted(() => {
  eventBus.on('xxx', receiveMessage);
});

//清理事件监听,避免内存泄漏 
onUnmounted(() => {
  eventBus.off('xxx', receiveMessage);
});
</script>

五、使用 provide/inject(隔辈通信)

使用props实现逐级透传 VS 使用provide-inject

      VS

provide() 函数:为组件后代提供数据

<script setup>
import { provide } from 'vue'

provide(/* 注入名 */ 'message', /* 值 */ 'hello!')
</script>

注:如果不使用 <script setup>,请确保 provide() 是在 setup() 同步调用的
参数:

  • 注入名:后代组件用注入名来查找期望注入的值;类型:字符串/Symbol
  • 提供的值:可以是任意类型的,包括响应式的状态

inject:注入上层组件提供的数据

<script setup>
import { inject } from 'vue'

const message = inject('message')
</script>

注:如果提供的值是一个 ref,注入进来的会是该 ref 对象,而不会自动解包为其内部的值。这使得注入方组件能够通过 ref 对象保持了和供给方的响应性链接。

六、useAttrs组件通信

1、useAttrs 的基本概念:

  • 用途:useAttrs 允许子组件访问和操作父组件传递的属性和事件,而无需显式地定义这些属性。
  • 场景:常用于构建高度可复用和灵活的组件,比如包装器组件或 UI 库组件。

2、基本用法:

<!-- MyButton.vue -->
<template>
  <button v-bind="attrs">

  </button>
</template>

<script setup>
import { useAttrs } from 'vue';

const attrs = useAttrs(); // 获取父组件传递的属性


</script>                        
<!-- Parent.vue -->
<template>  
    <MyButton type="submit" class="btn" @click="handleSubmit">提交  </MyButton>
</template>

type="submit" class="btn"是传递的属性:子组件可以通过 useAttrs 访问这些属性,并将它们应用于其内部的 DOM 元素

@click="handleSubmit":这是一个事件监听器,当子组件中的按钮被点击时,会调用父组件中的 handleSubmit 方法。

3、详细解释:

访问属性:

useAttrs():

  • 返回一个 Reactive 对象,包含所有传递给当前组件的非响应式属性。
  • 这些属性可以使用 v-bind 绑定到子组件的 DOM 元素上。

事件处理:

事件传递:

  • 子组件可以直接使用 @eventName 语法捕获父组件传递的事件。
  • 此外,子组件可以将事件处理逻辑封装在自己的方法中,进一步控制事件的处理。

4、总结

useAttrs 只获取非响应式属性。如果需要响应式数据,仍需使用 props。

七、Pinia

pinia的有关知识可以去参考:pinia(vue3)-CSDN博客

Pinia 是一个用于状态管理的库,通常用于替代 Vuex。它提供了一种简单且直观的方式来管理应用的全局状态,并支持组件之间的通信。

八、ref与$parent

  • ref在父组件中获取子组件实例对象
  • $parent可以在子组件内部获取父组件实例对象

以下的示例是从从父组件中控制子组件:

<template>
  <div>
    <h1>父组件计数: {{ count }}</h1>
    <Child ref="child" />
    <button @click="increment">增加</button>
  </div>
</template>

<script setup>
import { ref } from 'vue';
import Child from './Child.vue';

const count = ref(0); // 父组件的响应式数据
const child = ref(null); // 用于存储子组件的引用

const increment = () => {
  count.value++; // 增加父组件的计数
};

// 可以通过子组件的方法来更新父组件的状态
const updateFromChild = () => {
  // 调用子组件的某个方法
  child.value.updateCount();
};
</script>

子组件:

<template>
  <div>
    <h2>子组件</h2>

  </div>
</template>

<script setup>


const updateCount = () => {
    console.log('更新')
}
</script>

总结:

在 Vue 中,使用 ref 和$parent 是一种实现组件通信的方式,虽然这种方式在某些情况下有效,但通常不建议使用,因为它可能导致代码的耦合性增加和可维护性降低。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

useEffect简单介绍

react组件生命周期 比如说&#xff0c;某些操作就只在初始渲染后执行&#xff0c;我们就可以使用useEffect。 useEffect(function () {fetch(http://www.omdbapi.com/?apikey${KEY}&sinterstellar).then((res) > res.json()).then((data) > setMovies(data.Search)…

[C#][winform]基于yolov5的驾驶员抽烟打电话安全带检测系统C#源码+onnx模型+评估指标曲线+精美GUI界面

【重要说明】 该系统以opencvsharp作图像处理,onnxruntime做推理引擎&#xff0c;使用CPU进行推理&#xff0c;适合有显卡或者没有显卡windows x64系统均可&#xff0c;不支持macOS和Linux系统&#xff0c;不支持x86的windows操作系统。由于采用CPU推理&#xff0c;要比GPU慢。…

传统数据仓库升级版:云数据仓库!

随着公司业务拓展&#xff0c;数据爆炸性增长&#xff0c;数据驱动的见解已成为决策过程中关键指标。对公司来说&#xff0c;怎么选择存储所有这些信息的简单方法并运行必要的数据分析以获得有用的见解变得更加重要。 在过去的50多年里&#xff0c;传统的本地数据仓库一直是一…

ffmpeg视频滤镜:腐蚀滤镜

滤镜简述 erosion 官网链接> FFmpeg Filters Documentation 这个滤镜会在视频上应用腐蚀操作&#xff0c;腐蚀操作是形态学中一种操作&#xff0c;接触过opencv的同学应该很熟悉。滤镜主要有如下作用&#xff1a; 去除噪声&#xff1a;腐蚀可以帮助去除图像中的小颗粒噪…

构建后端为etcd的CoreDNS的容器集群(六)、编写自动维护域名记录的代码脚本

本文为系列测试文章&#xff0c;拟基于自签名证书认证的etcd容器来构建coredns域名解析系统。 一、前置文章 构建后端为etcd的CoreDNS的容器集群&#xff08;一&#xff09;、生成自签名证书 构建后端为etcd的CoreDNS的容器集群&#xff08;二&#xff09;、下载最新的etcd容…

pytorch训练和使用resnet

pytorch训练和使用resnet 使用 CIFAR-10数据集 训练 resnet resnet-train.py import torch import torchvision import torchvision.transforms as transforms import torch.nn as nn import torch.optim as optim# 在CIFAR-10数据集中 # 训练集&#xff1a;包含50000张图像…

城市极客,存内先锋-存内社区主理人招募令

在这个数据驱动的时代&#xff0c;存内计算正成为推动技术革新的核心力量。 我们&#xff0c;存内计算社区&#xff0c;正站在这场革命的前沿&#xff0c;现在&#xff0c;我们正式发出召集令&#xff0c;寻找那些渴望引领技术浪潮的城市站主理人&#xff01; 地点&#xff1a…

使用LangChain进行LLM应用开发(1)——了解LangChain

【课程链接】https://www.ai360labs.com/playground/course/66813572135124992/detail 【适用人群】 入门学习Langchain的同学轻体验ChatOpenAI的同学&#xff0c;平台提供Api-key&#xff0c;应该是很小的token额度&#xff0c;仅供练习 LangChain是一个开源框架&#xff0c…

【机器学习基础】全连接层

1. 定义: 每一个节点都跟其后面所有的神经元相连两层之间所有神经元都有权重连接,通常全连接层在卷积神经网络尾部也就是跟传统的神经网络神经元的连接方式是一样的 2. 作用: 全连接层(fully connected layers,FC)在整个卷积神经网络中起到“分类器”的作用。如果说卷积层、…

使用 NCC 和 PKG 打包 Node.js 项目为可执行文件(Linux ,macOS,Windows)

&#x1f3ac; 江城开朗的豌豆&#xff1a;个人主页 &#x1f525; 个人专栏 :《 VUE 》 《 javaScript 》 &#x1f4dd; 个人网站 :《 江城开朗的豌豆&#x1fadb; 》 ⛺️ 生活的理想&#xff0c;就是为了理想的生活 ! 目录 &#x1f4d8; 文章引言 步骤 1&#xff1a;…

linux:线程id及线程互斥

线程的tid不像进程&#xff0c;那不是他真正的id&#xff0c;也不是内核的lwp&#xff0c;而是由pthread库维护的一个唯一值 给用户提供的线程ID&#xff0c;不是内核中的lwp&#xff0c;而是pthread库维护的一个唯一值 库内部也要承担对线程的管理 #include<stdio.h>…

2024青龙面板京东教程

一、接上文《2024最新青龙面板安装教程》 腾讯云轻量服务器2核2G4M&#xff0c;只要79一年&#xff0c;可续费一次。 购买地址&#xff1a;https://curl.qcloud.com/LpLkvjq1 二、拉库 拉库前请打开青龙面板-配置文件 第18行 GithubProxyUrl“” 双引号中的内容清空 复制以…

代理 IP 对于鸿蒙开发者的意义与帮助

华为推出的鸿蒙操作系统以其独特的分布式架构和强大的性能&#xff0c;吸引了众多开发者的目光。而在鸿蒙开发的过程中&#xff0c;代理 IP 技术也发挥着重要的作用&#xff0c;为开发者带来了诸多意义与帮助。 一、提供更广泛的测试环境 对于鸿蒙开发者来说&#xff0c;确保应…

高效数据集成:聚水潭采购入库单与金蝶云星空

聚水潭采购入库单与金蝶云星空的高效数据集成案例分享 在企业日常运营中&#xff0c;采购入库单的数据处理和管理是至关重要的一环。为了实现聚水潭采购入库单到金蝶云星空的无缝对接&#xff0c;我们采用了轻易云数据集成平台&#xff0c;成功配置并运行了“聚水潭采购入库单…

钉钉录播抓取视频

爬取钉钉视频 免责声明 此脚本仅供学习参考&#xff0c;切勿违法使用下载他人资源进行售卖&#xff0c;本人不但任何责任! 仓库地址: GItee 源码仓库 执行顺序 poxyM3u8开启代理getM3u8url用于获取m3u8文件userAgent随机请求头downVideo|downVideoThreadTqdm单线程下载和…

荣耀MagicOS 9.0发布会及开发者大会丨一图读懂应用服务及商业合作分论坛

更多优质流量变现服务&#xff0c;可点击荣耀广告变现服务查看&#xff1b; 荣耀远航计划——应用市场【耀闪行动】全新上线&#xff0c;更多激励及资源扶持可点击荣耀应用市场耀闪行动查看。

Zookeeper实战 集群环境部署

1、概述 今天我们来学习一下Zookeeper集群相关的内容&#xff0c;本文主要的内容有集群环境的搭建&#xff0c;集群常见的问题和对应的解决方案。 2、集群环境搭建 2.1、准备工作 首先我们准备好安装包&#xff0c;创建好集群部署的路径。将解压后的安装文件复制三分。这里…

水轮发电机油压自动化控制系统解决方案介绍

在现代水电工程中&#xff0c;水轮机组油压自动化控制系统&#xff0c;不仅直接关系到水轮发电机组的安全稳定运行&#xff0c;还影响着整个水电站的生产效率和经济效益。 一、系统概述 国科JSF油压自动控制系统&#xff0c;适用于水轮发电机组调速器油压及主阀&#xff08;蝶…

【功能安全】 独立于环境的安全要素SEooC

目录 01 SEooC定义 02 SEooC开发步骤 03 SEooC开发示例 04 SEooC问答 01 SEooC定义 缩写: SEooC:Safety Element out of Context独立于环境的安全要素 SEooC出处:GB/T34590.10—2022,第9章节 SEooC与相关项什么关系? SEooC可以是系统、系统组合、子系统、软件组件、…

【Unity】游戏UI中添加粒子特效导致穿层问题的解决

这里介绍一下简易的ui系统中&#xff0c;添加粒子特效导致的穿层问题 首先是在ui界面中添加粒子特效预制体&#xff0c;这个时候&#xff0c;控制这个粒子显示层级的有两个方面 上图中&#xff0c;如果你的Sorting Layer ID的值&#xff08;Layer排序&#xff09;是大于当前C…