Vue 3 组件通信与状态管理:从基础到Pinia的全面解析

引言

Vue 3引入了Composition API,这为组件通信提供了更多的灵活性和强大的功能。例如,使用provideinject可以轻松实现跨层级组件的数据传递,而setup函数则为组件提供了更早的生命周期钩子,使得在组件初始化阶段就能进行通信设置。

父子组件通信的基本方式(props和$emit)

在Vue 3中,父子组件通信主要通过props和$emit实现。

  • Props:父组件通过props向子组件传递数据。在<script setup>中,使用defineProps来定义接收的props。
<!-- 父组件 -->
<template><ChildComponent :parentMessage="message" />
</template><script setup>
import { ref } from 'vue';
import ChildComponent from './ChildComponent.vue';const message = ref('Hello from parent!');
</script><!-- 子组件 -->
<script setup>
import { defineProps } from 'vue';const props = defineProps({parentMessage: String
});console.log(props.parentMessage); // 输出: Hello from parent!
</script>
  • 𝑒𝑚𝑖𝑡:子组件通过emit:子组件通过emit方法触发一个事件,并将数据作为参数传递给父组件。在<script setup>中,使用defineEmits`来声明可以触发的事件。
<!-- 子组件 -->
<script setup>
import { defineEmits } from 'vue';const emit = defineEmits(['child-event']);function triggerEvent() {emit('child-event', 'Data from child');
}
</script>
自定义事件的使用和原理

自定义事件在Vue中用于父子组件间的通信。父组件通过监听子组件发出的自定义事件来接收数据或执行某些操作。

  • 使用自定义事件:在<script setup>中,使用defineEmits来声明可以触发的事件,并在模板中使用v-on(或简写为@)来监听这些事件。
<!-- 父组件 -->
<template><ChildComponent @custom-event="handleCustomEvent" />
</template><script setup>
import { ref } from 'vue';
import ChildComponent from './ChildComponent.vue';function handleCustomEvent(data) {console.log(data); // 输出: Custom event data
}
</script><!-- 子组件 -->
<script setup>
import { defineEmits } from 'vue';const emit = defineEmits(['custom-event']);function triggerCustomEvent() {emit('custom-event', 'Custom event data');
}
</script>

简单的说就是,父组件用@×××占位表示接受子组件传过来的数据,:×××来向子组件传数据 ,子组件的话就是上面所示的defineProps方法和defineEmit来接受和向父组件传数据

在Vue 3中,v-model指令用于实现父子组件间的双向数据绑定。它是一个语法糖,背后实际上是结合了value prop和input事件的使用。v-model在组件上使用时,可以简化父组件和子组件之间的数据传递和事件处理。

vue3中的v-model

基本用法

假设我们有一个父组件和一个子组件,子组件需要实现一个输入框,父组件需要能够获取子组件输入框的值,并且当子组件的输入框值改变时,父组件的值也要相应更新。

子组件

在子组件中,我们定义一个props来接收父组件传递的值,并定义一个emit来向父组件发送值的变化。

<!-- ChildComponent.vue -->
<template><input type="text" :value="modelValue" @input="updateValue" />
</template><script setup>
import { defineProps, defineEmits } from 'vue';const props = defineProps({modelValue: String
});const emit = defineEmits(['update:modelValue']);const updateValue = (event) => {emit('update:modelValue', event.target.value);
};
</script>
父组件

在父组件中,我们使用v-model指令来绑定子组件的modelValue prop和父组件的某个数据属性。

<!-- ParentComponent.vue -->
<template><ChildComponent v-model="parentData" />
</template><script setup>
import { ref } from 'vue';
import ChildComponent from './ChildComponent.vue';const parentData = ref('');
</script>

高级用法

Vue 3还允许我们自定义v-model的行为,例如,我们可以改变v-model绑定的prop名称,或者改变触发更新的事件名称。

自定义prop和事件

在子组件中,我们可以使用defineEmits来声明自定义的事件名称,并在update:modelValue事件中使用它。

<!-- ChildComponent.vue -->
<script setup>
import { defineProps, defineEmits } from 'vue';const props = defineProps({customModelValue: String
});const emit = defineEmits(['update:customModelValue']);const updateValue = (event) => {emit('update:customModelValue', event.target.value);
};
</script>

在父组件中,我们使用v-model:customModelValue来绑定自定义的prop。

<!-- ParentComponent.vue -->
<template><ChildComponent v-model:customModelValue="parentData" />
</template><script setup>
import { ref } from 'vue';
import ChildComponent from './ChildComponent.vue';const parentData = ref('');
</script>

 

使用provide和inject实现跨层级通信

provideinject是Vue 3提供的两个新的API,用于实现跨层级组件的通信。provide函数允许你定义一个值,这个值可以被所有子组件注入。inject函数允许你注入一个由祖先组件提供的值。

<!-- 祖先组件 -->
<script setup>
import { provide } from 'vue';provide('globalState', reactive({ count: 0 }));
</script><!-- 子组件 -->
<script setup>
import { inject } from 'vue';const globalState = inject('globalState');
</script>

父组件通过provide传递的数据,子组件和子组件的子组件,以及子组件的子组件的子组件······(可多重套娃)都能通过inject接收

使用Pinia

Pinia 如何共享数据

Pinia 通过创建 store 来共享数据。store 是一个包含状态(state)、getter 和 actions 的容器。在 Pinia 中,store 是响应式的,这意味着当状态改变时,所有使用该状态的组件都会自动更新。

创建 Store

创建一个简单的计数器 store:

// stores/counterStore.js
import { defineStore } from 'pinia';export const useCounterStore = defineStore('counter', {state: () => ({count: 0,}),actions: {increment() {this.count++;},decrement() {this.count--;},},
});
使用 Store

在组件中,你可以通过 useStore 函数来访问 store:

<template><div><p>Count: {{ count }}</p><button @click="increment">Increment</button><button @click="decrement">Decrement</button></div>
</template><script setup>
import { useCounterStore } from '../stores/counterStore';const counterStore = useCounterStore();const count = computed(() => counterStore.count);
const increment = () => counterStore.increment();
const decrement = () => counterStore.decrement();
</script>
Pinia分包 

开发的产品大了,一个store肯定满足不了,我们可以这么搞:

步骤 1: 创建模块

在 src/stores/modules 目录下创建模块文件,例如 counterModule.js

// src/stores/modules/counterModule.js
import { defineStore } from 'pinia';export const useCounterModule = defineStore('counterModule', {state: () => ({count: 0,}),actions: {increment() {this.count++;},decrement() {this.count--;},},
});

步骤 2: 创建主 store

在 src/stores 目录下创建主 store 文件,例如 index.js

// src/stores/index.js
import { createPinia } from 'pinia';
import * as modules from './modules';export const useMainStore = createPinia();// 注册所有模块
Object.keys(modules).forEach((key) => {useMainStore.use(modules[key]);
});

步骤 3: 在主文件(如main.js)中使用主 store

在您的主文件(通常是 main.js 或 main.ts)中,使用 useMainStore 来引入主 store:

// main.js
import { createApp } from 'vue';
import App from './App.vue';
import { useMainStore } from './stores';const app = createApp(App);// 使用主 store
app.use(useMainStore);app.mount('#app');

步骤 4: 在组件中使用模块

在组件中,您可以直接通过模块的名称来访问模块中的状态和 actions:

<template><div><p>Count: {{ count }}</p><button @click="increment">Increment</button><button @click="decrement">Decrement</button></div>
</template><script setup>
import { useMainStore } from '../stores';const mainStore = useMainStore();const count = computed(() => mainStore.counterModule.count);
const increment = () => mainStore.counterModule.increment();
const decrement = () => mainStore.counterModule.decrement();
</script>

把所有pinia都导入到主store,这样无论调用哪个pinia都只用访问主store即可

 总结

组件通信方式

  1. Props & $emit

    • Props:从父组件向子组件传递数据。
    • $emit:子组件向父组件传递数据或触发事件。
  2. 自定义事件

    • 子组件使用defineEmits声明可触发的事件。
    • 父组件使用v-on@监听子组件的事件。
  3. v-model

    • 实现父子组件间的双向数据绑定。
    • 子组件通过modelValue prop和update:modelValue事件与父组件交互。
  4. provide/inject

    • 跨层级组件间通信,无需逐层传递props。
    • provide在祖先组件中提供数据。
    • inject在后代组件中注入数据。
  5. Pinia

    • 用于状态管理,创建和使用store来共享和管理应用的状态。
    • 可以创建多个store模块并组合使用。

如果这篇文章有帮助到你,给个点赞好吗

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

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

相关文章

Chrome调试工具

一、Chrome调试工具 1.Ctrl滚轮 可以放大开发者工具代码大小。 2.左边是 HTML 元素结构&#xff0c;右边是 CSS 样式。 3.右边 CSS 样式可以改动数值&#xff08;左右箭头或者直接输入&#xff09;和查看颜色。 4.Ctrl 0 复原浏览器大小。 5.如果点击元素&#xff0c;发现右侧…

Netfilter之连接跟踪(Connection Tracking)和反向 SNAT(Reverse SNAT)

连接跟踪&#xff08;Connection Tracking&#xff09; 连接跟踪是 Netfilter 框架中的一个功能&#xff0c;用于跟踪网络连接的状态和元数据。它使防火墙能够识别和处理数据包属于哪个连接&#xff0c;并在双向通信中正确匹配请求和响应数据包。 工作原理 建立连接&#xf…

微服务节流控制:Eureka中服务速率限制的精妙配置

微服务节流控制&#xff1a;Eureka中服务速率限制的精妙配置 在微服务架构中&#xff0c;服务的可用性和稳定性对于整个系统的性能至关重要。Eureka作为Netflix开源的服务发现框架&#xff0c;虽然主要用于服务注册与发现&#xff0c;但合理地配置服务的速率限制也是确保服务健…

【C语言】深入解析选择排序

文章目录 什么是选择排序&#xff1f;选择排序的基本实现代码解释选择排序的优化选择排序的性能分析选择排序的实际应用结论 在C语言编程中&#xff0c;选择排序是一种简单且直观的排序算法。尽管它在处理大型数据集时效率不高&#xff0c;但由于其实现简单&#xff0c;常常用于…

基于协同过滤混合算法的餐饮推荐系统设计与实现

基于协同过滤混合算法的餐饮推荐系统设计与实现 Design and Implementation of Restaurant Recommendation System Based on Hybrid Collaborative Filtering Algorithm 完整下载链接:基于协同过滤混合算法的餐饮推荐系统设计与实现 文章目录 基于协同过滤混合算法的餐饮推荐…

牛客TOP101:反转链表

文章目录 1. 题目描述2. 解题思路3. 代码实现 1. 题目描述 2. 解题思路 简单粗暴的写法&#xff0c;就是从头到尾挨个将所有结点的指向翻转即可。需要注意的是&#xff0c;翻转之后会失去原有指向的结点&#xff0c;所以需要提前保存。   具体做法就是&#xff0c;使用cur标记…

面试必备!Redis面试题合集

目录 1.Redis简介 2. 分布式缓存常见的技术选型方案有哪些? 3. 说一下 Redis 和 Memcached 的区别和共同点 4. 缓存数据的处理流程是怎样的? 5. 为什么要用 Redis/为什么要用缓存? 6. Redis 常见数据结构以及使用场景分析 6.1. string 6.2. list 6.3. hash 6.4. s…

Spring源码注解篇二:手写@Component注解

Component注解的功能 在Spring框架中&#xff0c;Component 注解是一个核心特性&#xff0c;用于自动检测类并将其注册为Spring应用上下文中的Bean。这大大简化了Bean的配置过程&#xff0c;使得开发者能够通过注解的方式快速地将类标记为组件&#xff0c;并由Spring容器进行管…

硬件检测工具 | CPU-Z v2.10.0 官方中文绿色版

软件简介 CPU-Z是一款广受欢迎的硬件检测工具&#xff0c;主要用于收集电脑处理器的详细信息。这款软件能够提供关于CPU的详细数据&#xff0c;包括处理器名称、编号、代号、进程和缓存等信息。此外&#xff0c;CPU-Z还能实时监测每个内核的内部频率和内存频率&#xff0c;以及…

【洛谷B3644】【模板】拓扑排序 / 家谱树 解题报告

洛谷B3644 - 【模板】拓扑排序 / 家谱树 题目描述 有个人的家族很大&#xff0c;辈分关系很混乱&#xff0c;请你帮整理一下这种关系。给出每个人的后代的信息。输出一个序列&#xff0c;使得每个人的后辈都比那个人后列出。 输入格式 第 1 1 1 行一个整数 N N N&#xf…

Java字节流的输入输出

Java字节流的输入输出指的是使用Java中的字节流来进行数据的读取和写入操作。字节流是以字节为单位进行读写操作的&#xff0c;常用于处理二进制数据或者字符数据。 Java中常用的字节流类有InputStream和OutputStream。InputStream用于读取字节数据&#xff0c;OutputStream用…

【运维项目经历|037】MFS-Scale分布式对象存储系统部署与优化项目

🍁博主简介: 🏅云计算领域优质创作者 🏅2022年CSDN新星计划python赛道第一名 🏅2022年CSDN原力计划优质作者 ​ 🏅阿里云ACE认证高级工程师 ​ 🏅阿里云开发者社区专家博主 💊交流社区:CSDN云计算交流社区欢迎您的加入! 目录 项目名称 项目背景 项目目标 …

如何在项目中打印sql和执行的时间

目标&#xff1a;打印DAO方法中sql和执行的时间 一种方式是去实现Mybatis的拦截器Interceptor &#xff0c;比较麻烦&#xff1b; 这里介绍一种比较简单的实现方式&#xff1b; 1、如何打印sql&#xff1f; 配置文件加这个可以打印出com.zhenhui.ids.busi.watch包下执行的sq…

c++包管理器

conan conan search&#xff0c;查看网络库 conan profile detect&#xff0c;生成缓存信息conan new cmake_exe/cmake_lib&#xff0c;创建cmakelists.txtconan install .&#xff0c;执行Conanfile.txt中的配置&#xff0c;生成相关的bat文件 项目中配置Conanfile.txt(或者…

ImportError: DLL load failed while importing _swigfaiss: 找不到指定的模块。

ImportError: DLL load failed while importing _swigfaiss: 找不到指定的模块 这个错误通常是由于系统中缺少某些必要的动态链接库&#xff08;DLL&#xff09;文件&#xff0c;或者由于与当前环境中的库版本不兼容导致的。以下是一些解决这个问题的步骤&#xff1a; 方法一&…

linux高级编程(sqlite数据库调用)

数据库 1、分类&#xff1a; 大型 中型 小型 ORACLE MYSQL/MSSQL SQLITE DBII powdb 关系型数据库 2、名词&#xff1a; DB 数据库 select update database DBMS 数据库管理系统 MIS 管理…

tessy 集成测试:小白入门指导手册

目录 1,创建集成测试模块且分析源文件 2,设置测试环境 3,TIE界面设置相关函数 4,SCE界面增加用例 5,编辑数据 6,用例所对应的测试函数序列 7,添加 work task 函数 8,为测试场景添加函数 9,为函数赋值 10,编辑时间序列的数值 11,执行用例 12,其他注意事项…

《昇思25天学习打卡营第2天|初学教程/快速入门》

文章目录 快速入门处理数据集网络构建模型训练保存模型加载模型 快速入门 通过MindSpore的API来快速实现一个简单的深度学习模型。 MindSpore 是华为推出的一个全场景深度学习框架&#xff0c;它旨在实现易开发、高效执行和全场景覆盖的目标。这个框架支持云、边缘以及端侧场…

零基础STM32单片机编程入门(十四) DS18B20温度传感器模块实战含源码

文章目录 一.概要二.DS18B20主要性能参数三.DS18B20温度传感器内部框图四.DS18B20模块原理图五.DS18B20模块跟单片机板子接线和通讯时序1.单片机跟DS18B20连接示意图2.单片机跟DS18B20通讯流程与时序3.通讯流程中的9个数据字节内容格式4.温度数据寄存器LSB/MSB格式 六.STM32单片…

ROS2入门到精通—— 1-3 ROS1移植到ROS2系统梳理

ROS2同一功能包只能同时包含Python或者C一种 1 ROS1 && ROS2 CMakeList.txt ROS1中CMakeLists.txt架构如下&#xff1a; cmake_minimum_required() #CMake的最低版本号project() #项目名称find_package() #找到编译需要的其他CMake/Catkin package catkin_py…