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

Vue 3 组合式 API 规范配合 Pinia

实现效果:
根据pinia中存储的不同状态,
点击不同的按钮,切换不同的弹窗和标题

1. Pinia Store(组合式写法)

// stores/dataStore.ts
import { defineStore } from 'pinia'
import { reactive } from 'vue'type DialogType = 'type1' | 'type2'
//定义一个接口规范
interface DialogState {id: numbername: stringvisible: boolean
}export const useDataStore = defineStore('dataType', () => {// 状态定义 两个不同的状态const state = reactive({dialogs: {type1: { id: 1, name: '数据1', visible: false },type2: { id: 2, name: '数据2', visible: false }} as Record<DialogType, DialogState>,showDownloadList: false})// Actionsconst toggleDialog = (type: DialogType, visible: boolean) => {// 在切换之前-关闭所有对话框Object.keys(state.dialogs).forEach(key => {state.dialogs[key as DialogType].visible = false})// 再打开目标对话框state.dialogs[type].visible = visible}return {...toRefs(state), // 保持响应式解构toggleDialog}
})

2. 按钮组件(组合式写法)

<!-- Buttons.vue -->
<template><div class="header-box"><el-button type="primary" size="large" @click="openDialog('type1')">类型弹窗1</el-button><el-button type="primary" size="large" @click="openDialog('type2')">类型弹窗2</el-button></div>
</template><script setup lang="ts">
import { useExportDataStore } from '../store'const exportStore = useExportDataStore()
//调用store中的方法
const openDialog = (type: 'type1' | 'type2') => {exportStore.toggleDialog(type, true)
}
</script>

3. 弹窗组件(组合式写法)

<!-- ExportDialog.vue -->
<template><el-dialog v-model="currentDialog.visible" :title="currentDialog.name" width="800"@close="onClose"><!-- 动态渲染表单 --><component :is="currentDialog.id === 1 ? Type1Form : Type2Form"v-model="formData"/><template #footer><el-button @click="onClose">取消</el-button><el-button type="primary" @click="onSubmit">确定</el-button></template></el-dialog>
</template><script setup lang="ts">
import { computed, ref } from 'vue'
import { useExportDataStore } from '../store'const exportStore = useExportDataStore()
const { dialogs } = storeToRefs(exportStore)// 计算当前活跃的对话框
const currentDialog = computed(() => {return Object.values(dialogs.value).find(d => d.visible) || dialogs.value.type1
})// 动态表单数据
const formData = ref({name: '',region: ''
})const onClose = () => {exportStore.toggleDialog(currentDialog.value.id === 1 ? 'type1' : 'type2', false)
}const onSubmit = () => {console.log('提交数据:', {type: currentDialog.value.name,data: formData.value})onClose()
}
</script>

4. 表单子组件示例(组合式写法)

<!-- GoodsForm.vue -->
<template><el-form :model="modelValue"><el-form-item label="类型1" :label-width="formLabelWidth"><el-input v-model="modelValue.name" /></el-form-item><el-form-item label="类型2" :label-width="formLabelWidth"><el-select v-model="modelValue.region"><el-option label="电子产品" value="digital" /><el-option label="服装" value="clothes" /></el-select></el-form-item></el-form>
</template><script setup lang="ts">
defineProps({modelValue: {type: Object,required: true}
})const formLabelWidth = '100px'
</script>

关键优化点说明

  1. 类型安全的 Store

    • 使用 TypeScript 明确定义 DialogTypeDialogState
    • 通过泛型确保状态结构安全
  2. 自动对话框切换

    const currentDialog = computed(() => {return Object.values(dialogs.value).find(d => d.visible) || dialogs.value.goods
    })
    
    • 自动检测当前应显示的对话框
    • 避免手动维护显示状态
  3. 动态组件渲染

    <component :is="currentDialog.id === 1 ? Type1 : Type2" />
    
    • 根据对话框类型动态切换表单组件
    • 减少模板中的条件判断
  4. 单一数据源

    • 所有对话框状态集中管理
    • 通过 toggleDialog action 统一控制
  5. 响应式处理

    • 使用 storeToRefs 保持解构后的响应式
    • 表单数据使用 ref 实现双向绑定

组合式 API 的优势

  1. 逻辑复用

    • 可以轻松提取 useDialog 等 composable 函数
  2. 类型推导

    • 更好的 TypeScript 支持
  3. 代码组织

    • 相关逻辑可以集中在一起(如表单处理与对话框控制)
  4. 性能优化

    • 精确控制响应式依赖

对比选项式 API 的改进

特性选项式 API组合式 API
代码组织按选项分块按功能聚合
类型支持需要额外类型标注天然支持类型推导
逻辑复用Mixins/插件Composables
响应式处理自动代理 data显式声明 ref/reactive
Pinia 集成需在每个方法中调用 useStore在 setup 中一次性调用

这种实现方式既保持了组合式 API 的灵活性,又通过 Pinia 提供了专业的状态管理方案,适合中大型项目使用。

这个 computed 计算属性的作用是自动找出当前应该显示的对话框


代码解析

const currentDialog = computed(() => {return Object.values(dialogs.value).find(dialog => dialog.visible) || dialogs.value.goods
})
1. Object.values(dialogs.value)
  • dialogs 是一个 Pinia store 中的响应式对象,结构如下:
    dialogs: {goods: { id: 1, name: '类型1', visible: false },orders: { id: 2, name: '类型2', visible: false }
    }
    
  • Object.values() 会提取对象的所有值,返回:
    [{ id: 1, name: '类型1', visible: false },{ id: 2, name: '类型2', visible: false }
    ]
    
2. .find(dialog => dialog.visible)
  • 遍历数组,找到第一个 visible: true 的对话框
  • 例如:当点击"导出商品数据"按钮后,dialogs.type1.visible 会变为 true,此时会返回:
    { id: 1, name: '类型1', visible: false },
    
3. || dialogs.value.goods
  • 如果所有对话框都不可见(visible: false),则默认返回 type1 对话框
  • 这是为了防止 currentDialog 返回 undefined(防御性编程)

场景说明

有两个相似弹窗
但同一时间只需要显示一个对话框

currentDialog 会自动:

  1. 检测哪个对话框应该显示
    通过检查 visible 状态,确定用户点击的是哪个按钮。

  2. 提供统一的数据源
    在模板中可以直接用 currentDialog 绑定,在弹窗关闭之前清空组件内容。无需写重复逻辑:

    <el-dialog v-model="currentDialog.visible" :title="currentDialog.name":before-close="close"
    ><!-- 内容 -->
    </el-dialog>
    

具体工作流程

1. 用户点击"类型1"按钮

设置 type1.visible = true

exportStore.toggleDialog('type1', true) 
2. currentDialog 自动更新
  • Object.values(dialogs.value) 会得到:
    [{ id: 1, name: '类型1', visible: false },// type1{ id: 2, name: '类型2', visible: false }// type2
    ]
    
  • .find() 会找到第一个 visible: true 的项(即 type1
  • 模板中的 el-dialog 会显示类型1对话框
3. 用户点击"类型2"按钮
exportStore.toggleDialog('type2', true) // 设置 type2.visible = true
  • 此时 type1.visible 会自动设为 false(如果你在切换时关闭其他对话框)
  • currentDialog 会切换到 orders

为什么不用 v-if="dialogs.type1.visible"

虽然可以直接写:

<el-dialog v-if="dialogs.goods.visible" ...>
<el-dialog v-if="dialogs.orders.visible" ...>

但使用 currentDialog 的优势在于:

  1. 避免重复代码:只需维护一个 <el-dialog> 模板
  2. 动态扩展:如果未来新增更多导出类型(如 users),只需在 store 中添加配置,无需修改模板
  3. 逻辑集中:对话框的切换逻辑完全由计算属性处理,更清晰

如何确保同一时间只显示一个对话框?

可以在 toggleDialog 方法中添加逻辑:

// 在 Pinia store 中
actions: {toggleDialog(type: DialogType, visible: boolean) {// 关闭所有其他对话框Object.keys(this.dialogs).forEach(key => {this.dialogs[key].visible = false})// 打开当前对话框this.dialogs[type].visible = visible}
}

这样当你打开一个对话框时,其他对话框会自动关闭。

相关文章:

Vue 3 组合式 API 规范配合 Pinia

实现效果&#xff1a; 根据pinia中存储的不同状态&#xff0c; 点击不同的按钮&#xff0c;切换不同的弹窗和标题1. Pinia Store&#xff08;组合式写法&#xff09; // stores/dataStore.ts import { defineStore } from pinia import { reactive } from vuetype DialogType …...

JavaSpring 中使用 Redis

创建项目 配置 Redis 服务地址 创建 Controller 类 由于当前只是些简单的测试代码&#xff0c;所以就不进行分层了&#xff0c;只创建一个 Controller 来实现 jedis 通过 jedis 对象里的各种方法来操作 Redis 此处通过 StringRedisTemplate 来操作 Redis 最原始提供的类是 Re…...

多线程使用——线程安全、线程同步

一、线程安全 &#xff08;一&#xff09;什么是线程安全问题 多个线程&#xff0c;同时操作同一个共享资源的时候&#xff0c;可能会出现业务安全的问题。 &#xff08;二&#xff09;用程序摹拟线程安全问题 二、线程同步 &#xff08;一&#xff09;同步思想概述 解决线…...

Spring Boot 集成 tess4j 实现图片识别文本

tesseract是一个开源的光学字符识别&#xff08;OCR&#xff09;引擎&#xff0c;它可以将图像中的文字转换为计算机可读的文本。支持多种语言和书面语言&#xff0c;并且可以在命令行中执行。它是一个流行的开源OCR工具&#xff0c;可以在许多不同的操作系统上运行。 Tess4J是…...

JAVA IO、BIO、NIO、AIO及零拷贝

概述 IO,常写作 I/O,是 Input/Output 的简称,是 Input/Output 的简称,即输入/输出。通常指数据在内部存储器(内存)和外部存储器(硬盘、优盘等)或其他周边设备之间的输入和输出。 目前有三种 IO 共存。分别是 BIO、NIO 和 AIO。 BIO 全称 Block-IO 是一种同步且阻塞的…...

Redis命令——list

列表类型是用来存储多个有序的字符串&#xff0c;列表中的每个字符串称为元素&#xff08;element&#xff09;&#xff0c;⼀个列表最多可以存储个元素 在 Redis 中&#xff0c;可以对列表两端插入&#xff08;push&#xff09;和弹出&#xff08;pop&#xff09;&#xff0c;…...

MicroDEM 与 OpenEV(FWTtools工具包):两款开源DEM相关小软件

大家好&#xff0c;今天为大家介绍的软件是MicroDEM 与 OpenEV&#xff0c;这两款小软件分别主要用于DEM数据的处理、数据查看与分析。MICRODEM是一款专注于地理空间分析和遥感数据处理的开源小软件。 MICRODEM官网网址为&#xff1a;https://microdem.org/&#xff0c;官网比较…...

大学英语四级选词填空阅读题和段落匹配解析

Leisure and well - being休闲和幸福 The vital role of leisure in enhancing well - being休闲在增进福祉方面的重要作用 A) The perception of leisure activities has a significant impact on the mental health advantages they offer. 对休闲活动的看法对其提供的心理…...

STM32使用rand()生成随机数并显示波形

一、随机数生成 1、加入头文件&#xff1a;#include "stdlib.h" 2、定义一个用作生成随机数种子的变量并加入到滴答定时器中不断自增&#xff1a;uint32_t run_times 0; 3、设置种子&#xff1a;srand(run_times);//每次生成随机数前调用一次为佳 4、生成一个随…...

大语言模型智能体:安全挑战与应对之道

在当今科技飞速发展的时代&#xff0c;大语言模型驱动的智能体正逐渐融入我们生活和工作的方方面面&#xff0c;给我们带来了诸多便利。但与此同时&#xff0c;它们的安全问题也引起了广泛的关注。今天&#xff0c;咱们就一起来深入了解一下可信大语言模型智能体所面临的安全挑…...

每日OJ_牛客_kotori和素因子_DFS_C++_Java

目录 牛客_kotori和素因子_DFS 题目解析 C代码 Java代码 牛客_kotori和素因子_DFS kotori和素因子 描述&#xff1a; kotori拿到了一些正整数。她决定从每个正整数取出一个素因子。但是&#xff0c;kotori有强迫症&#xff0c;她不允许两个不同的正整数取出相同的素因子…...

Vue 开发实战:从入门到精通的经验之谈

零基础入门 Vue&#xff0c;10 分钟快速上手教程 一、初识 Vue二、搭建 Vue 开发环境&#xff0c;迈开第一步 Vue 核心概念大揭秘&#xff0c;响应式系统原来是这么回事儿三、Vue 核心概念&#xff1a;响应式系统 模板语法与表达式&#xff0c;玩转 Vue 就靠它啦四、模板语法与…...

快手OneRec 重构推荐系统:从检索排序到生成统一的跃迁

文章目录 1. 背景2. 方法2.1 OneRec框架2.2 Preliminary2.3 生成会话列表2.4 利用奖励模型进行迭代偏好对齐2.4.1 训练奖励模型2.4.2 迭代偏好对齐 3. 总结 昨天面试的时候聊到了OneRec&#xff0c;但是由于上次看这篇文章已经是一个月之前&#xff0c;忘得差不多了&#xff0c…...

c# 简单实现将Message的内容保存到txt中,超过100个则清理旧文件

using System; using System.IO; using System.Threading;public static class LogManager {private static readonly object _fileLock new object(); // 线程安全锁private const int MaxFiles 100; // 最大文件数限制private const string LogDire…...

精打细算 - GPU 监控

精打细算 - GPU 监控 在上一篇,咱们历经千辛万苦,终于让应用程序在 Pod 的“驾驶舱”里成功地“点火”并用上了 GPU。太棒了!但是,车开起来是一回事,知道车速多少、油耗多少、引擎水温是否正常,则是另一回事,而且同样重要,对吧? 我们的 GPU 应用跑起来了,但新的问题…...

软件测试的页面交互标准:怎样有效提高易用性

当用户遇到"反人类"设计时 "这个按钮怎么点不了&#xff1f;"、"错误提示完全看不懂"、"我输入的内容去哪了&#xff1f;"——这些用户抱怨背后&#xff0c;都指向同一个问题&#xff1a;页面交互的易用性缺陷。作为软件测试工程师&a…...

共享单车出行规律与决定因素的空间交互分析——以北京六大区为例

共享单车出行规律与决定因素的空间交互分析——以北京六大区为例 原文&#xff1a;Spatial Interaction Analysis of Shared Bicycles Mobility Regularity and Determinants: A Case Study of Six Main Districts, Beijing 这篇文章主要研究了北京六个主要城区共享单车的流动…...

Windows上安装FFmpeg的详细指南

1.下载FFmpeg 访问FFmpeg官方下载页面&#xff1a;https://ffmpeg.org/download.html 点击"Windows builds from gyan.dev"或"Windows builds by BtbN" gyan.dev版本&#xff1a;https://www.gyan.dev/ffmpeg/builds/ BtbN版本&#xff1a;https://githu…...

React-在使用map循环数组渲染列表时须指定唯一且稳定值的key

在渲染列表的时候&#xff0c;我们须给组件或者元素分配一个唯一值的key, key是一个特殊的属性&#xff0c;不会最终加在元素上面&#xff0c;也无法通过props.key来获取&#xff0c;仅在react内部使用。react中的key本质是服务于diff算法, 它的默认值是null, 在diff算法过程中…...

Nodejs数据库单一连接模式和连接池模式的概述及写法

概述 单一连接模式和连接池模式是数据库连接的两种主要方式&#xff1a; 单一连接模式&#xff1a; 优点&#xff1a;实现简单&#xff0c;适合小型应用缺点&#xff1a;每次请求都需要创建新连接&#xff0c;连接创建和销毁开销大&#xff0c;并发性能差&#xff0c;容易出…...

作业2 CNN实现手写数字识别

# 导入必要库 import numpy as np import matplotlib.pyplot as plt import seaborn as sns # 用于高级可视化 from tensorflow import keras from tensorflow.keras import layers from sklearn.metrics import confusion_matrix, ConfusionMatrixDisplay import time # 用于…...

整流二极管详解:原理、作用、应用与选型要点

一、整流二极管的基本定义 整流二极管是一种利用PN结单向导电性将交流电&#xff08;AC&#xff09;转换为直流电&#xff08;DC&#xff09;的半导体器件。其核心特性是正向导通、反向截止&#xff0c;允许电流仅沿单一方向流动。 典型结构&#xff1a;硅材料&#xff08;正向…...

WordPress自定义页面与文章:打造独特网站风格的进阶指南

文章目录 引言一、理解WordPress页面与文章的区别二、主题与模板层级&#xff1a;自定义的基础三、自定义页面模板&#xff1a;打造专属页面风格四、自定义文章模板&#xff1a;打造个性化文章呈现五、使用自定义字段和元数据&#xff1a;增强内容灵活性六、利用WordPress钩子&…...

PHP最新好看UI个人引导页网页源码

PHP最新好看UI个人引导页网页源码 采用PHP、HTML、CSS及JavaScript等前端技术&#xff0c;构建了一个既美观又实用的个人主页解决方案。 源码设计初衷在于提供一个高度可定制、跨平台兼容的模板&#xff0c;让用户无需深厚的编程基础&#xff0c;即可快速搭建出专业且富有创意的…...

jQuery — 动画和事件

介绍 jQuery动画与事件是提升网页交互的核心工具。动画方面&#xff0c;jQuery通过简洁API实现平滑过渡效果&#xff0c;提供预设方法如slideUp()&#xff0c;支持.animate()自定义CSS属性动画&#xff0c;并内置队列系统实现动画链式执行。开发者可精准控制动画速度、回调时机…...

arkTs:使用回调函数的方法实现子组件向父组件传值

使用回调函数的方法实现子组件向父组件传值 1 主要内容说明2 实现步骤2.1 父组件中定义回调函数2.2 子组件声明并调用回调函数2.3 注意事项 3 源码3.1 父组件3.2 子组件3.3 源码效果显示截图 4 结语5 定位日期 1 主要内容说明 本文源码是一套 父组件与子组件之间双向数据传递的…...

VBA 调用 dll 优化执行效率

问题描述 之前excel 用vba写过一个应用&#xff0c;请求的是aws lambda 后端, 但是受限于是云端服务&#xff0c;用起来响应特别慢&#xff0c;最近抽了点时间准备优化下&#xff0c;先加了点日志看看是哪里慢了 主方法代码如下&#xff0c;函数的主要目的是将 Excel 工作簿的…...

【机器学习-周总结】-第4周

以下是本周学习内容的整理总结&#xff0c;从技术学习、实战应用到科研辅助技能三个方面归纳&#xff1a; 文章目录 &#x1f4d8; 一、技术学习模块&#xff1a;TCN 基础知识与结构理解&#x1f539; 博客1&#xff1a;【时序预测05】– TCN&#xff08;Temporal Convolutiona…...

Django-Friendship 项目常见问题解决方案

Django-Friendship 项目常见问题解决方案 django-friendship Django app to manage following and bi-directional friendships 项目地址: https://gitcode.com/gh_mirrors/dj/django-friendship Django-Friendship 是一个基于 Django 的应用&#xff0c;它允许创建和管…...

C语言用if else求三个数最小值的一题多解

一、问题引入 假设x,y,z为整数,使用if else语句求x,y,z三个数中的最小值? 二、三种解法 第一种解法: #include<stdio.h> int main(){int x,y,z,min;printf("请输入三个整数&#xff1a;");scanf_s("%d %d %d", &x, &y, &z);//初始值…...