vue3常用的组件间通信

一 props

props 可以实现父子组件通信,props数据是只读。

1. 基本用法

在父组件中,你可以这样传递 props:

<template><ChildComponent message="Hello, Vue 3!" />
</template><script setup>
import ChildComponent from './ChildComponent.vue';
</script>

在 Vue 3 的 <script setup> 语法中,你可以使用 defineProps 来定义 props:

<script setup>
import { defineProps } from 'vue';const props = defineProps({title: String,count: Number
});
</script>

在传统的 export default 语法中,可以这样定义:

export default {props: {title: {type: String,required: true},count: {type: Number,default: 0}}
};

2. 类型和默认值

  • 类型:确保传递给组件的 props 类型正确,Vue 会进行类型检查。
const props = defineProps({title: String,  // 只接受字符串count: {type: Number,  // 只接受数字default: 0     // 默认值}
});
  • 默认值:如果没有提供 props,组件将使用定义的默认值。
const props = defineProps({count: {type: Number,default: 0}
});

3. 组件的 props 验证

你可以定义自定义验证逻辑:

const props = defineProps({age: {type: Number,validator: value => value >= 18 // 只接受18岁及以上}
});

4. 注意事项

  • 不可变性:props 是只读的,子组件不能直接修改父组件传递过来的 props。如果需要修改,应该在子组件内部创建一个本地副本:
<script setup>
import { ref, computed } from 'vue';const props = defineProps(['count']);
const localCount = ref(props.count);const increment = () => {localCount.value++;
};
</script>
  • 响应式:如果 props 是对象或数组,确保你在子组件中使用时能够保持其响应性。
  • 性能考虑:如果传递的 props是大型数据结构,如数组或对象,确保你的组件能够有效地处理这些数据。避免在子组件中直接进行深度操作,以防止性能问题。
  • 组件封装:合理使用 props 有助于组件的封装和复用,保持组件的单一职责和可测试性。

二 自定义事件

自定义事件用于在子组件和父组件之间传递信息

1. 在子组件中触发事件

使用 emit 方法触发自定义事件:

<script setup>
import { defineEmits } from 'vue';const emit = defineEmits(['my-event']);const triggerEvent = () => {emit('my-event', 'Hello from child');
};
</script><template><button @click="triggerEvent">Trigger Event</button>
</template>

2. 在父组件中监听事件

使用 v-on 或简写 @ 监听自定义事件:

<template><ChildComponent @my-event="handleMyEvent" />
</template><script setup>
import ChildComponent from './ChildComponent.vue';const handleMyEvent = (message) => {console.log(message); // 输出 "Hello from child"
};
</script>

3. 事件参数

子组件触发的事件可以带有参数,这些参数会传递给父组件的事件处理函数。可以传递任意类型的数据(如字符串、数字、对象等)。

// 子组件
const triggerEvent = () => {emit('my-event', 'Hello from child', 123);
};// 父组件
const handleMyEvent = (message, number) => {console.log(message, number); // 输出 "Hello from child" 123
};

4 组件解耦

子组件应通过自定义事件向父组件发送消息,而不是直接修改父组件的数据。这样可以保持组件的独立性和可重用性。

<!-- 子组件 -->
<template><button @click="notifyParent">Notify Parent</button>
</template><script setup>
import { defineEmits } from 'vue';
const emit = defineEmits(['notify']);const notifyParent = () => {emit('notify', 'Data');
};
</script><!-- 父组件 -->
<template><ChildComponent @notify="handleNotify" />
</template><script setup>
import ChildComponent from './ChildComponent.vue';const handleNotify = (data) => {console.log(data); // 输出 "Data"
};
</script>

三 v-model

在 Vue 3 中,v-model 的原理基于双向数据绑定。其核心是通过 modelValueupdate:modelValue 事件来实现的。具体来说:

  1. 父组件:使用 v-model 绑定到子组件的 modelValue 属性。
  2. 子组件:通过 modelValue 属性接收数据,并在需要时通过 emit('update:modelValue', newValue)触发更新事件,将新值传递回父组件。

在 Vue 3 中,v-model 的默认行为可以被自定义,允许为不同的 props 和事件指定不同的名称。可以通过 v-model:propName@update:propName 的方式来指定。

1 原理

v-model 实现了双向绑定,其底层机制涉及两个主要的部分:

  1. 数据绑定:v-model 将父组件的一个数据属性绑定到子组件的 modelValue 属性。
  2. 事件更新:子组件通过触发 update:modelValue 事件来通知父组件更新数据属性。
  3. 简化流程示意:
  • 数据绑定:
<ChildComponent v-model="parentValue" />

在这个例子中,parentValue 是父组件的数据属性,v-model 将其绑定到ChildComponent 组件的 modelValue 属性上。

  • 数据传递:
<input :value="modelValue" @input="updateValue" />

子组件的 input 元素将 modelValue 作为其值,并监听 input 事件。

  • 事件触发:
function updateValue(event) {emit('update:modelValue', event.target.value);
}

当用户在输入框中输入内容时,子组件触发 update:modelValue 事件,将新的值传递给父组件。

2 基本用法:

在父组件中使用 v-model 绑定数据到子组件的 props 中,子组件通过 emit 触发更新:

父组件

<template><ChildComponent v-model:message="parentMessage" />
</template><script setup>
import { ref } from 'vue';
const parentMessage = ref('Hello World');
</script>

子组件

<template><input :value="message" @input="$emit('update:message', $event)" />
</template><script setup>
import { defineProps, defineEmits } from 'vue';
const props = defineProps(['message']);
const emit = defineEmits();
</script>

3 自定义 v-model:

Vue 3 允许自定义 v-model 的 prop 名称:

父组件

<template><CustomComponent v-model:customProp="value" />
</template><script setup>
import { ref } from 'vue';
const value = ref('Hello');
</script>

子组件

<template><input :value="customProp" @input="$emit('update:customProp', $event)" />
</template><script setup>
import { defineProps, defineEmits } from 'vue';
const props = defineProps(['customProp']);
const emit = defineEmits();
</script>

4 多个 v-model:

支持在一个组件上使用多个 v-model:

父组件

<template><MultipleModelComponent v-model:title="title" v-model:content="content" />
</template><script setup>
import { ref } from 'vue';
const title = ref('Title');
const content = ref('Content');
</script>

子组件

<template><input :value="title" @input="$emit('update:title', $event)" /><textarea :value="content" @input="$emit('update:content', $event)" />
</template><script setup>
import { defineProps, defineEmits } from 'vue';
const props = defineProps(['title', 'content']);
const emit = defineEmits();
</script>

四 provide 和 inject

在 Vue 3 中,provide 和 inject 是用来在组件层级中共享数据的一种机制。它们特别适用于跨级传递数据,而不需要通过每一级的 props 和事件传递。这种机制适合于较复杂的应用场景,比如主题配置、用户认证状态等。

1 provide 和 inject 的基本用法

1. provide 和 inject 的作用

  • provide: 在父组件中定义,可以将数据提供给其所有子组件(包括嵌套的子组件)。
  • inject: 在子组件中定义,用于接收从祖先组件提供的数据。

父组件:使用 provide 提供数据

<template><div><h1>Parent Component</h1><child-component /></div>
</template><script setup>
import { provide } from 'vue';
import ChildComponent from './ChildComponent.vue';const data = 'Shared Data';
provide('sharedData', data); // 提供数据
</script>

在这个父组件中,我们使用 provide 传递了一个名为 ‘sharedData’ 的数据,所有子组件(及其嵌套的子组件)都可以通过 inject 来访问这个数据。

子组件:使用 inject 接收数据

<template><div><h2>Child Component</h2><p>{{ sharedData }}</p></div>
</template><script setup>
import { inject } from 'vue';const sharedData = inject('sharedData'); // 接收数据
</script>

在这个子组件中,我们使用 inject 来接收从父组件中提供的数据 ‘sharedData’,并可以在模板中使用它。

2 provide 和 inject 的进阶用法

1. 提供响应式数据

提供响应式数据(如 ref 或 reactive),使得数据在多个组件中保持同步。

<template><div><h1>Parent Component</h1><child-component /></div>
</template><script setup>
import { provide, ref } from 'vue';
import ChildComponent from './ChildComponent.vue';const count = ref(0);
provide('count', count); // 提供响应式数据
</script>

在子组件中,你可以直接修改和使用这个响应式数据:

<template><div><h2>Child Component</h2><p>Count: {{ count }}</p><button @click="count++">Increment</button></div>
</template><script setup>
import { inject } from 'vue';const count = inject('count'); // 接收响应式数据
</script>

2. 使用 provide 和 inject 进行依赖注入
对于较复杂的应用,可以在多个组件之间共享更复杂的对象或函数。例如,可以用来注入服务或工具函数。

<template><div><h1>App Component</h1><child-component /></div>
</template><script setup>
import { provide } from 'vue';
import ChildComponent from './ChildComponent.vue';const apiService = {fetchData() {return 'Data from API';}
};provide('apiService', apiService); // 提供服务
</script>

在子组件中,你可以注入并使用这个服务:

<template><div><h2>Child Component</h2><p>{{ data }}</p></div>
</template><script setup>
import { inject } from 'vue';const apiService = inject('apiService');const data = apiService.fetchData(); // 使用服务
</script>

3 总结

  • provide: 在父组件中定义,用来提供数据或服务给其所有子组件。
  • inject: 在子组件中定义,用来接收从父组件提供的数据或服务。
  • 可以使用响应式数据来确保跨组件的状态同步。
  • 适用于复杂的应用程序中需要跨组件传递和共享数据的场景。
  • provide 和 inject 是 Vue 3 强大的功能之一,能够帮助你更灵活地管理组件之间的状态和依赖。

五 refs

$refs 是 Vue.js 提供的一种机制,用于直接访问 DOM 元素或子组件实例。你可以在模板中使用 ref 特性来为 DOM 元素或组件指定一个引用名,然后在 Vue 实例或组件的代码中通过 $refs 来访问这些引用。

在 Vue 3 中,使用 ref 访问子组件时,通常需要通过 expose 来暴露一些方法或数据,以便父组件能够访问。你需要在子组件中使用defineExpose 来明确暴露的内容。这样,父组件就可以直接通过 ref 获取到这些数据或方法

  1. 用法
  • 访问 DOM 元素
<template><input ref="myInput" type="text" /><button @click="focusInput">Focus Input</button>
</template><script setup>
import { ref, onMounted } from 'vue';const myInput = ref(null);const focusInput = () => {myInput.value.focus(); // 访问并操作 DOM 元素
};onMounted(() => {console.log(myInput.value); // 在组件挂载后访问 DOM 元素
});
</script>
  • 访问子组件实例

子组件:
在子组件中使用 defineExpose 来暴露你想要的数据或方法。例如:

<template><div>{{ internalValue }}</div>
</template><script setup>
import { ref, defineExpose } from 'vue';const internalValue = ref('Hello, World!');defineExpose({internalValue
});
</script>

父组件:
在父组件中使用 ref 获取子组件的实例,然后访问暴露的数据或方法:

<template><ChildComponent ref="child" /><button @click="showValue">Show Value</button>
</template><script setup>
import { ref } from 'vue';
import ChildComponent from './ChildComponent.vue';const child = ref(null);const showValue = () => {alert(child.value.internalValue);
};
</script>
  1. 优缺点

优点:

  • 直接访问 DOM 元素或子组件实例,适用于需要直接操作或获取 DOM 元素或组件的方法。
  • 可以在组件初始化后执行 DOM 操作,避免了过早访问 DOM 元素的问题。

缺点:

  • 过度使用 ref 可能会使组件的耦合度变高,使组件之间的关系变得复杂。
  • 不应过多依赖 ref 来解决问题,应该优先考虑使用 props 和 events 进行数据传递和事件处理。

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

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

相关文章

WebPage-Bootstrap框架(container类,container-fluid类,栅格系统)

1.Bootstrap Bootstrap为页面内容和栅格系统包裹了一个.container容器&#xff0c;框架预先定义类 1.1container类 响应式布局容器的宽度 手机-小于768px 宽度设置100%&#xff1b; 平板-大于等于768px 设置宽度为750px 桌面显示器-大于等于992px 设置宽度 970px 大屏幕显…

【Bug解决】Nacos启动成功,但却无法访问(提示:无法访问此网站,192.168.10.88的响应时间过长)

情形如下&#xff1a;第一次启动运行一些正常&#xff0c;非正常关闭虚拟机&#xff0c;第二次启动虚拟机查看容器状态如下&#xff1a; docker nacos容器一切正常启动&#xff0c;但是就是无法访问web控制面板&#xff0c;访问无法连接。 首先&#xff1a;执行命令查看日志 …

设置元素浮动,出现高度塌陷导致鼠标无法点击

先贴代码片段&#xff1a; <div style"width: 30%; float: left;"><nz-input-group nzSearch [nzAddOnAfter]" suffixIconButton"><input type"text" nz-input placeholder"请输入实验名称" [(ngModel)]"q.name&…

glTF格式:WebGL应用的3D资产优化解决方案

摘要 glTF作为一种高效的3D资产格式&#xff0c;为WebGL、OpenGL ES和OpenGL运行时的应用提供了强有力的支持。它不仅简化了3D模型的传输与加载流程&#xff0c;还通过优化资产大小&#xff0c;使得打包、解包更加便捷。本文将深入探讨glTF格式的优势&#xff0c;并提供实用的代…

ClickHouse 与 Quickwit 集成实现高效查询

1. 概述 在当今大数据分析领域&#xff0c;ClickHouse 作为一款高性能的列式数据库&#xff0c;以其出色的查询速度和对大规模数据的处理能力&#xff0c;广泛应用于在线分析处理 (OLAP) 场景。ClickHouse 的列式存储和并行计算能力使得它在处理结构化数据查询时极具优势&…

初探shell与bash使用指南

文章目录 一、shell二、bash第一步、新建脚本第二步、添加权限第三步、执行bash脚本 在日常开发中&#xff0c;经常使用到Linux服务器相关知识&#xff0c;输入命令获取想要的结果&#xff0c;本篇介绍shell 与 bash的相关知识。 一、shell 是命令行解释器&#xff0c;接收用户…

nlohmann json:读写json文件

读写json文件是经常的操作,可以通过如下的方式完成: #include <string> #include <iostream> #include <fstream> #include <filesystem> #include <nlohmann/json.hpp>using namespace std; using json = nlohmann::json; namespace fs = st…

使用nc命令检测UDP端口

使用nc命令检测UDP端口也是非常的简单&#xff0c;需要注意的是&#xff0c;所安装nc的版本不同&#xff0c;使用选项有点差异。 1、检测开启的UDP nc -vuz 192.168.2.201 5353 nc -vuz 192.168.2.201 37430 端口正常启用时&#xff0c;会提示“UDP packet sent successful…

深入解析网络通信关键要素:IP 协议、DNS 及相关技术

我的主页&#xff1a;2的n次方_ 1. IP 协议报头结构 4 位版本&#xff1a;表示 IPv4 / IPv6 4 位首部长度&#xff1a;表示 IP 报头的长度&#xff0c;以 4 字节为单位 8 位服务类型&#xff1a;包括 3 位优先权字段&#xff08;已弃用&#xff09;&#xff0c;4 位 TOS 字…

电路 - 笔记2

1 555 芯片 2 类比 - pU*I 与 Fm*a 是不是可以与牛顿定律类比 - Fm*a 人的力量&#xff08;F&#xff09;有限。 当推大箱子&#xff08;m&#xff09;时&#xff0c;加速度&#xff08;a&#xff09;就不会很大 当推小箱子&#xff08;m&#xff09;时&#xff0c;加速度…

分布式框架 - ZooKeeper

一、什么是微服务架构 1、单体架构 顾名思义一个软件系统只部署在一台服务器上。 ​ 在高并发场景中&#xff0c;比如电商项目&#xff0c;单台服务器往往难以支撑短时间内的大量请求&#xff0c;聪明的架构师想出了一个办法提高并发量&#xff1a;一台服务器不够就加一台&am…

球体检测系统源码分享

球体检测检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Computer Vision …

Ubuntu20.04点击文件闪退

在 Ubuntu 系统下&#xff0c;如果点击文件按钮导致系统闪退&#xff0c;可以尝试以下几种解决方法&#xff1a; 更新系统和应用程序&#xff1a; 确保你的系统和所有应用程序都是最新版本。可以通过终端执行以下命令来更新系统&#xff1a; sudo apt update sudo apt upgrade重…

python爬虫解析神器Xpath——lxml库(9)

文章目录 1、Xpath1.1 什么是xpath?1.2 xpath的原理1.3 xml介绍1.3.1 什么是xml?1.3.2 xml和html的区别?1.3.3 xml文档的节点关系1.4 xpath语法的使用1.4.1 选取节点1.4.2 选取未知节点1.4.3 同时使用多个路径表达式2、lxml库2.1 介绍2.2 基础使用2.3 文件读取html文档2.4 实…

springboot实战学习笔记(5)(用户登录接口的主逻辑)

接着上篇博客学习。上篇博客是已经基本完成用户模块的注册接口的开发以及注册时的参数合法性校验。具体往回看了解的链接如下。 springboot实训学习笔记&#xff08;4&#xff09;(Spring Validation参数校验框架、全局异常处理器)-CSDN博客文章浏览阅读576次&#xff0c;点赞7…

Agile Modbus STM32裸机移植 从机使用

本教程手把手教你实现Agile Modbus,照抄就能成。 并且会解读函数功能含义。 1. 引言 Agile Modbus 是一个轻量级的 Modbus 协议栈,可以满足用户在任何场景下的需求。 功能 支持 rtu 和 tcp 协议,使用纯 C 语言开发,不涉及任何硬件接口,可以直接在任何形式的硬件上使用。由…

序列化与反序列化深入分析:UUID案例的实践与JSON转换对比

在Java开发中&#xff0c;序列化和反序列化是非常重要的概念。序列化是将对象的状态转换为字节流的过程&#xff0c;而反序列化则是将字节流恢复为对象的过程。本文将以UUID序列化案例和JSON转换为例&#xff0c;深入探讨这两者的具体实现及应用场景。 1. Java 序列化与反序列化…

深入理解Spring Data JPA与接口编程

目录 1. 什么是Spring Data JPA&#xff1f; 2. 如何使用Spring Data JPA&#xff1f; 3. 示例代码 4. 使用Query注解 5. 拓展知识&#xff1a;接口编程的好处 6. 结论 在软件开发领域&#xff0c;接口&#xff08;Interface&#xff09;是一种定义了方法签名但没有实现的…

Fyne ( go跨平台GUI )中文文档-小部件 (五)

本文档注意参考官网(developer.fyne.io/) 编写, 只保留基本用法 go代码展示为Go 1.16 及更高版本, ide为goland2021.2 这是一个系列文章&#xff1a; Fyne ( go跨平台GUI )中文文档-入门(一)-CSDN博客 Fyne ( go跨平台GUI )中文文档-Fyne总览(二)-CSDN博客 Fyne ( go跨平台GUI…

给子组件传递dom元素引用实例方案

在实际开发中有一个比较常见的场景是&#xff0c;父组件写了一个el-form组件。然后里面内容很多&#xff0c;所以拆成了子组件。那么子组件中就有调用父组件的form实例方法的需求。到所以这就涉及一个问题&#xff0c;怎么把父组件的form实例传递给子应用。 这里传递后直接调用…