vue3常用的组件间通信

news2024/9/20 5:38:01

一 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.coloradmin.cn/o/2148078.html

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

相关文章

【Verilog学习日常】—牛客网刷题—Verilog快速入门—VL24

边沿检测 有一个缓慢变化的1bit信号a&#xff0c;编写一个程序检测a信号的上升沿给出指示信号rise&#xff0c;当a信号出现下降沿时给出指示信号down。 注&#xff1a;rise,down应为单脉冲信号&#xff0c;在相应边沿出现时的下一个时钟为高&#xff0c;之后恢复到0&#xff0…

116页PPT麦肯锡方法详解-用简单的方法做复杂的事

读者朋友大家好&#xff0c;最近有会员朋友咨询晓雯&#xff0c;需要《116页PPT麦肯锡方法详解-用简单的方法做复杂的事》资料&#xff0c;欢迎大家文末扫码下载学习。 以下是在实际工作中应用麦肯锡问题解决法的具体方式&#xff1a; 一、项目管理与流程优化领域 界定问题 …

再看Java-笔试

放在前面的话 最近确实有些空闲&#xff0c;分配的功能从一开始的两眼一黑到现在的一上午就能完成&#xff0c;这何尝不是一种进步呢。 该说不说&#xff0c;海康的API问题相比较其他第三方的API还是蛮多的&#xff0c;而且10月份人工客服还会停运&#xff0c;不过到那个时候…

LeetCode54. 螺旋矩阵(2024秋季每日一题 21)

给你一个 m 行 n 列的矩阵 matrix &#xff0c;请按照 顺时针螺旋顺序 &#xff0c;返回矩阵中的所有元素。 示例 1&#xff1a; 输入&#xff1a;matrix [[1,2,3],[4,5,6],[7,8,9]] 输出&#xff1a;[1,2,3,6,9,8,7,4,5] 示例 2&#xff1a; 输入&#xff1a;matrix [[1,…

由于安全风险,安全领导者考虑禁止人工智能编码

安全团队与开发团队之间的紧张关系 83% 的安全领导者表示&#xff0c;他们的开发人员目前使用人工智能来生成代码&#xff0c;57% 的人表示这已成为一种常见做法。 然而&#xff0c;72% 的人认为他们别无选择&#xff0c;只能允许开发人员使用人工智能来保持竞争力&#xff0…

【Unity】对象池 - 未更新完

自定义泛型对象池 文章目录 自定义泛型对象池封装泛型类例子 使用Unity自带对象池 封装泛型类 public abstract class MyPool<T> : MonoBehaviour where T :Component {[SerializeField] protected T prefab; // 生成的预制体[SerializeField] protected int defaultNum…

Delphi5利用DLL实现窗体的重用

文章目录 效果图参考利用DLL实现窗体的重用步骤1 设计出理想窗体步骤2 编写一个用户输出的函数或过程&#xff0c;在其中对窗体进行创建使它实例化步骤3 对工程文件进行相应的修改以适应DLL格式的需要步骤4 编译工程文件生成DLL文件步骤5 在需要该窗体的其他应用程序中重用该窗…

8.sklearn-模型保存

文章目录 环境配置&#xff08;必看&#xff09;头文件引用1.保存模型代码工程运行结果生成文件 2.加载模型代码工程运行结果 环境配置&#xff08;必看&#xff09; Anaconda-创建虚拟环境的手把手教程相关环境配置看此篇文章&#xff0c;本专栏深度学习相关的版本和配置&…

HTML基础和常用标签

“合抱之木&#xff0c;生于毫末&#xff1b;九层之台&#xff0c;起于累土&#xff1b;千里之行&#xff0c;始于足下。” 文章目录 前言文章有误敬请斧正 不胜感恩&#xff01;1. HTML的基本结构解释&#xff1a; 2. 常见标签的介绍2.1 标题和文本2.2 链接和图片2.3 列表2.4 …

云安全 | AWS S3存储桶安全设计缺陷分析

什么是AWS S3&#xff1f; 默认情况下&#xff0c;Amazon S3 是安全的。创建后&#xff0c;只有资源所有者才能访问他们创建的 Amazon S3 资源。 Amazon S3 支持用户身份验证来控制对数据的访问。您可以使用存储桶策略和访问控制列表 (ACL)等访问控制机制来有选择地向用户和用…

solidwork直线画圆弧的操作

效果如下&#xff1a; 踩过好多坑了。 首先选择直线 先点一下这个点拉出来再回到这个点&#xff08;这个过程点一次就可以了&#xff09;&#xff0c;注意注意一定要这么做&#xff01;否则没有圆弧

prime1靶机渗透 (信息收集 内核提权)

靶机信息 vulnhub靶机 prime1 主机发现 -sn 是scan and no port hack 只用于主机发现 ┌──(kali㉿kali)-[~] └─$ sudo nmap -sn 192.168.50.0/24 Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-09-09 02:25 EDT Nmap scan report for 192.168.50.1 Host is up …

web学习——day1

1.web标准 2.html和css 此时&#xff0c;学完这一部分&#xff0c;你web的具体的结构已经有了 但是呢&#xff0c;这还是太单调了&#xff0c;我们应该加点儿样式&#xff0c;这就该用到CSS了 CSS引入方式 样式1&#xff1a;颜色 样式2&#xff1a;哪怕对于同一类事物&#xf…

消息队列-Kafka(概念篇)

1 为什么需要消息队列&#xff1f; 消息队列是一种基于消息的异步通信机制&#xff0c;用于在分布式系统中不同组件或服务之间传递数据和通知。实际上可以将消息队列看作为存放消息的容器&#xff0c;参与消息传递的分别称为生产者&#xff08;发送消息&#xff09;和消费者&am…

【macOS】【zsh报错】zsh: command not found: python

【macOS】【zsh Error】zsh: command not found: python 本地已经安装了Python&#xff0c;且能在Pycharm中编译Python程序并运行。 但是&#xff0c;在macOS终端&#xff0c;运行Python&#xff0c;报错。 首先要确认你在macOS系统下&#xff0c;是否安装了Python。 如果安…

打不开Qtcreator(This application fail to start...........)

目录 今天突然打不开Qtcreator,报错如下 解决方案 1.检查环境变量配置(我就是通过这个解决好的) 2.如果也弹出跟我一样的AMD窗口,可以更新AMD驱动试试 3.重装qtcreator 4.检查 qtcreator下的bin\plugins\platforms是否缺少提示的相关.dll文件 总结 今天突然打不开Qtcreat…

马来西亚交通标志检测系统源码分享

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

VSCode语法提示的配置

ctrlshiftP打开Command Palette,运行C/Cpp: Edit configurations...生成c_cpp_properties.json c_cpp_properties.json是什么&#xff1f; 这个文件主要是用于VSCode语法提示的配置&#xff0c;例如&#xff1a;指定 include 路径&#xff0c;问题匹配类型等。CtrlShiftP打开C…

nvm list available报错Could not retrieve https://nodejs.org/dist/index.json.

今天在查看nvm list available时出现如下错误&#xff1a; 首先找到nvm所在文件夹settings.txt 打开此文件后&#xff0c;加入两段代码&#xff0c;如果有就替换掉 node_mirror: https://npmmirror.com/mirrors/node/ npm_mirror: https://npmmirror.com/mirrors/npm/ 再次运行…

Android轻量级RTSP服务使用场景分析和设计探讨

技术背景 好多开发者&#xff0c;对我们Android平台轻量级RTSP服务模块有些陌生&#xff0c;不知道这个模块具体适用于怎样的场景&#xff0c;有什么优缺点&#xff0c;实际上&#xff0c;我们的Android平台轻量级RTSP服务模块更适用于内网环境下、对并发要求不高的场景&#…