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

[Vue3 + TS + Vite]文件选择器-组件

文件选择器组件代码

<script setup lang="ts">
import { ref, onMounted, defineProps, defineEmits, computed, toRaw } from 'vue';// 定义props
interface Props {buttonTextUnactive?: string;buttonTextActive?: string;onFatherClick?: boolean;
}// 定义emits
interface Emits {(e: 'file-selected', files: File[]): void;(e: 'picker-canceled'): void;
}const props = defineProps<Props>();
const emits = defineEmits<Emits>();// 状态
const isPickerActive = ref(false);
const selectedFiles = ref<File[]>([]);// 初始化按钮文本
const buttonText = computed(() => {let defaultButtonText = {unactive: '选择文件',active: '文件选择器已打开'};return isPickerActive.value ?(props.buttonTextActive ? props.buttonTextActive : defaultButtonText.active) :(props.buttonTextUnactive ? props.buttonTextUnactive : defaultButtonText.unactive);
});// 文件选择器由父组件click事件响应
const onFatherClick = computed(() => {return props.onFatherClick === true;
});const fatherClick = async () => {console.log('props', props.onFatherClick);console.log('onFatherClick', onFatherClick.value);await openFilePicker(); // 等待文件选择器的结果const result = toRaw(selectedFiles.value);return result; // 返回文件选择的结果
};// 外部触发文件选择器
const handleClick = () => {if (isPickerActive.value) return;openFilePicker();
};// 打开文件选择器
const openFilePicker = async () => {isPickerActive.value = true;try {const files = await window.showOpenFilePicker();selectedFiles.value = Array.from(files);console.log('组件--file-selected');emits('file-selected', selectedFiles.value);} catch (error) {console.log('组件--picker-canceled');emits('picker-canceled');} finally {isPickerActive.value = false;}
};onMounted(() => {// 添加监听器// 清理return () => {};
});defineExpose({fatherClick,
});
</script><template><div><button v-if="onFatherClick" :disabled="isPickerActive">{{ buttonText }}</button><button v-else @click="handleClick" :disabled="isPickerActive">{{ buttonText }}</button><!-- <pre v-if="selectedFiles.length > 0">{{ selectedFiles }}</pre> --></div>
</template>

父组件调用代码

调用方法1-子组件触发Click事件:
<script setup lang="ts">
import { ref } from "vue";const cc_click = ref();const onFileSelected = (files: File[]) => {console.log('父组件--文件已选择:', files);
};const onPickerCanceled = () => {console.log('父组件--文件选择被取消');
};
</script><template><file-selector ref="cc_click" @file-selected="onFileSelected" @picker-canceled="onPickerCanceled" />
</template>
调用方法2-父组件触发Click事件:
<script setup lang="ts">
import { ref } from "vue";const cc_click = ref();const onFileSelected = (files: File[]) => {console.log('父组件--文件已选择:', files);
};const onPickerCanceled = () => {console.log('父组件--文件选择被取消');
};const click_select = async () => {let value = await cc_click.value.fatherClick();console.log('cc_click', value);
};
</script><template><file-selector ref="cc_click" :onFatherClick="true" @click="click_select"@file-selected="onFileSelected" @picker-canceled="onPickerCanceled"/>
</template>

经验笔记

之所以不选择使用input标签file种类,是因为input标签file种类存在原生的缺陷,无法响应文件选择器关闭取消事件。

  1. 组件设计:

    • Props: 定义了三个props: buttonTextUnactive, buttonTextActive, 和 onFatherClick。这些props允许父组件自定义按钮文本和控制文件选择器的触发方式。
    • Computed Properties: buttonText 是一个计算属性,用于根据isPickerActive和传递的props来动态显示按钮文本。
    • State Management: 使用ref来管理组件状态,如isPickerActiveselectedFiles
    • Exposing Methods: 通过defineExpose暴露fatherClick方法给父组件,以便父组件能够触发文件选择器。
  2. 事件处理:

    • Emit Events: 使用emits定义了两个事件: file-selectedpicker-canceled。这些事件在文件选择后或用户取消选择时被触发。
    • Handling Clicks: 如果onFatherClicktrue,则按钮不绑定点击事件,而是等待父组件调用fatherClick方法。否则,点击事件由组件内部处理。
  3. 模板结构:

    • Conditional Rendering: 根据onFatherClick的值来条件渲染不同的按钮。
    • Button Interaction: 按钮根据isPickerActive的值禁用或启用。
  4. 生命周期钩子:

    • Setup Cleanup: 使用onMounted来添加和移除事件监听器,确保组件正确清理。
  5. 父组件使用:

    • Method 1: 使用ref获取组件实例,并通过事件监听器来响应文件选择结果。
    • Method 2: 通过ref调用fatherClick方法来触发文件选择器,并通过事件监听器来响应文件选择结果。
  6. 注意事项:

    • showOpenFilePicker API: 这个API需要在安全的上下文中使用,例如HTTPS,并且只在部分现代浏览器中可用。
    • showOpenFilePicker关闭事件: showOpenFilePicker没有原生的关闭事件,这里通过try/catch来模拟文件选择器关闭的情况。
  7. 调试与测试:

    • Console Logs: 在关键位置添加console logs来调试流程。
    • Testing Scenarios: 测试不同的场景,包括选择文件、取消选择、多次打开文件选择器等。

结论

这个组件提供了一种灵活的方式来创建文件选择器,允许父组件自定义外观和行为,并通过事件和方法与组件进行交互。它使用Vue 3的现代特性,如<script setup>语法糖和ref/computed,使得代码简洁高效。

参考链接:
Window:showOpenFilePicker() 方法

相关文章:

[Vue3 + TS + Vite]文件选择器-组件

文件选择器组件代码 <script setup lang"ts"> import { ref, onMounted, defineProps, defineEmits, computed, toRaw } from vue;// 定义props interface Props {buttonTextUnactive?: string;buttonTextActive?: string;onFatherClick?: boolean; }// 定…...

Chrome书签搜索插件

效果展示 这是一个chroma插件&#xff0c;可以按住 ctrl/command B 进行搜索您的书签&#xff0c;并且点击打开您的书签。支持上下切换回车打开新页面。 扩展下载地址 bookmark-search 欢迎有任何问题给我提 issues...

MATLAB算法实战应用案例精讲-【人工智能】联邦学习(二)(附python代码实现)

目录 前言 几个高频面试题目 面向隐私保护的机器学习(PPML)和安全机器学习(Secure ML)的区别: 联邦学习、安全计算是什么关系? 联邦学习有哪些类型?如何区分横向联邦学习和纵向联邦学习? 什么是IID?什么是Non-iid? 联邦学习训练后的模型是一个公共的模型,而…...

在 C++ 中实现一个简单的图形用户界面(GUI)应用

在 C 中实现一个简单的图形用户界面&#xff08;GUI&#xff09;应用 图形用户界面&#xff08;GUI&#xff09;应用程序是现代软件开发中不可或缺的一部分。它们为用户提供了直观的交互方式&#xff0c;使得操作更加简单和高效。本文将介绍如何在 C 中实现一个简单的 GUI 应用…...

如何编写一个CMakeLists.txt文件(由简到难,较详细)

在Linux系统下&#xff0c;经常使用CMakeLists.txt文件来链接、编译C工程&#xff0c;大部分人clone的代码里都是有CMakeLists.txt文件的&#xff0c;只需要cmake .. 和make就完事了&#xff0c;但在工作中&#xff0c;你必须要有从无到有编写CMakeLists.txt文件的能力。 一、…...

数据结构----链表

一丶概念 链表又称单链表、链式存储结构&#xff0c;用于存储逻辑关系为“一对一”的数据。 和顺序表不同同&#xff0c;使用链表存储数据&#xff0c;不强制要求数据在内存中集中存储&#xff0c;各个元素可以分散存储在内存中。 二丶特点 特点&#xff1a;内存不连续…...

【Qt】内置对话框

一.Qt内置对话框 Qt 提供了多种可复⽤的对话框类型&#xff0c;即 Qt 标准对话框。Qt标准对话框全部继承于QDialog类。常⽤标准对话框如下&#xff1a; 二.内置对话框分类 1.消息对话框 QMessageBox 1.1 概念 消息对话框是应⽤程序中最常⽤的界⾯元素。消息对话框主要⽤于为…...

excel常规操作

一、去重 IF(COUNTIF($D$1:D2,D2)>1,"",C2) —— D是去重的列 二、不同列匹配 VLOOKUP(A1,E:F,2,0) vlookup(查找值, 查找区域, 返回查找区域的第几列数据, 精确查找输入参数"0"or"false" 或 模糊查找输入参数"1"or"true…...

uniapp webview子页面向父页面发送数据和触发事件,重点在第3条!!!

1、众所周知H5中iframe可以用过postmessage进行&#xff0c;从H5子页面向H5父页面进行通信。方法如下&#xff1a; // 子页面 window.parent.postMessage({ data: 你的消息 }, *);// 父页面 <iframe src"xxxxxxxxxxx"></iframe> window.addEventListene…...

【STM32实物】基于STM32+ESP32+手机APP设计的智能宠物喂食系统实物源码原理图PCB设计文档演示视频——(文末工程资料下载)

基于STM32+ESP32+手机APP设计的智能宠物喂食系统 演示视频 基于STM32+ESP32+手机APP设计的智能宠物喂食系统 摘 要 近年来,宠物在人们生活中越来越不可或缺,给人们带来的陪伴和快乐。然而,由于种种原因,主人不能时刻照顾宠物的饮食,所以宠物喂食装置变得尤为重要。传…...

EMC学习笔记5——辐射骚扰发射

辐射骚扰发射是基本的实验项目&#xff0c;目的是检验设备在工作时有没有产生意外的过强电磁辐射。 例如发电机&#xff0c;在工作时会产生意外的电磁波辐射&#xff0c;因为电子设备中隐藏了一些天线&#xff0c;这些隐藏的天线在辐射电磁波。 一、两种基本的天线结构 如前面…...

深入理解浏览器解析机制和XSS向量编码

基础部分 1.<a href"%6a%61%76%61%73%63%72%69%70%74:%61%6c%65%72%74%28%31%29">aaa</a> <a>标签可以识别&#xff0c;但是解析不了&#xff0c; 是在协议的编码顺序上&#xff0c;先认协议 URL 编码 "javascript:alert(1)" 2.<a …...

winform 大头针实现方法——把窗口钉在最上层

平时我们再使用成熟的软件的时候&#xff0c;会发现有个大头针的功能挺不错的。就是点一下大头针&#xff0c;窗口就会钉住&#xff0c;一直保持在最上面一层&#xff0c;这样可以一边设置参数&#xff0c;一边观察这个窗口里面的变化&#xff0c;比较方便。下面我就来简单实现…...

中间件|day1.Redis

Redis 定义 Redis 是一个开源&#xff08;BSD许可&#xff09;的&#xff0c;内存中的数据结构存储系统&#xff0c;它可以用作数据库、缓存和消息中间件。 它支持多种类型的数据结构&#xff0c;如 字符串&#xff08;strings&#xff09;&#xff0c; 散列&#xff08;hash…...

PMP到底有什么用?

PMP 就是项目管理证书&#xff0c;全称是项目管理专业人士资格认证&#xff0c;对于一个在项目管理岗位混迹五年的老油条来说&#xff0c;PMP 证书是敲开项目管理岗位的第一块砖&#xff0c;每年考 PMP 的人都很多&#xff0c;要是 PMP 证书没有价值&#xff0c;还会有那么多人…...

apache huidi 时间旅行Time Travel)机制

Apache Hudi(Hadoop Upserts Deletes and Incrementals)是一个数据管理框架,它帮助你高效地管理存储在分布式存储系统(如HDFS或云存储)上的大型数据集。其一个关键特性是“时间旅行”,这允许你在特定时间点查询数据的历史版本。 什么是Apache Hudi中的时间旅行? Apach…...

Python 数据可视化,怎么选出合适数据的图表

数据可视化最佳实践 1. 引言&#xff1a;为什么数据可视化最佳实践很重要 数据可视化是数据分析和决策过程中不可或缺的一部分。通过有效的可视化&#xff0c;复杂的数据可以转化为易于理解的信息&#xff0c;从而帮助观众快速做出正确的判断。然而&#xff0c;糟糕的可视化可…...

c# 元组

文章目录 元组的定义元组的使用示例使用场景创建一个列表 在 C# 中&#xff0c;元组&#xff08;Tuple&#xff09;是一种用于存储多个值的数据结构&#xff0c;它可以方便地将不同类型的多个值打包在一起。元组在 C# 7.0 及更高版本中得到了增强&#xff0c;允许更方便地创建和…...

自定义注解

目录 使用注解定义分布式锁 Aop例子 retention 表示在什么时候可以用&#xff0c;runtime表示在运行期可以用 target表示可以用在哪些上面 inherited表示可以被继承 切点和切面类 重点是 pjp.proceed(args) 这个就是执行目标方法&#xff0c;下面的这一段没啥意思 也可…...

报错:Can‘t find Python executable “python“, you can set the PYTHON env variable

将项目导入vscode,执行npm install命令后&#xff0c;报错了&#xff0c;报错的信息是node-sass安装失败&#xff0c;同时提示需要python环境的错误信息&#xff0c;这是因为安装node-sass失败了&#xff0c;而node-sass依赖于Python环境。 1.报错&#xff1a;Cant find Python…...

Windows虚拟控制器驱动完全指南:如何用ViGEmBus实现游戏设备模拟

Windows虚拟控制器驱动完全指南&#xff1a;如何用ViGEmBus实现游戏设备模拟 【免费下载链接】ViGEmBus Windows kernel-mode driver emulating well-known USB game controllers. 项目地址: https://gitcode.com/gh_mirrors/vi/ViGEmBus 你是否曾因游戏只支持特定手柄而…...

终极DBeaver多线程查询优先级控制:基于查询类型的动态调整指南

终极DBeaver多线程查询优先级控制&#xff1a;基于查询类型的动态调整指南 【免费下载链接】dbeaver DBeaver 是一个通用的数据库管理工具&#xff0c;支持跨平台使用。* 支持多种数据库类型&#xff0c;如 MySQL、PostgreSQL、MongoDB 等&#xff1b;提供 SQL 编辑、查询、调试…...

三步解锁QQ空间历史说说备份:数据留存与管理实用指南

三步解锁QQ空间历史说说备份&#xff1a;数据留存与管理实用指南 【免费下载链接】GetQzonehistory 获取QQ空间发布的历史说说 项目地址: https://gitcode.com/GitHub_Trending/ge/GetQzonehistory QQ空间数据备份是许多用户保存青春记忆和重要记录的需求。GetQzonehist…...

Windows下OpenClaw全流程指南:GLM-4.7-Flash模型接入与自动化测试

Windows下OpenClaw全流程指南&#xff1a;GLM-4.7-Flash模型接入与自动化测试 1. 为什么选择OpenClawGLM-4.7-Flash组合 去年我在处理一个Python数据分析项目时&#xff0c;每天要重复执行十几个脚本并整理结果。当我第三次因为手工操作失误导致数据错乱后&#xff0c;终于决…...

agent实习面经(十一)

来自网络&#xff0c;侵删 先完成&#xff0c;再完美 某东&#xff0c;某节1.LLM 为什么有幻觉&#xff0c;如何减少 LLM 幻觉&#xff1f;1.1概率生成机制&#xff1a;LLM 本质是基于统计概率预测下一个 token&#xff0c;而非检索事实数据库。当训练数据中缺乏确切信息或模…...

百川2-13B-4bits模型微调实践:提升OpenClaw特定任务准确率

百川2-13B-4bits模型微调实践&#xff1a;提升OpenClaw特定任务准确率 1. 为什么需要微调百川模型&#xff1f; 去年冬天&#xff0c;当我第一次用OpenClaw自动整理电脑上的技术文档时&#xff0c;发现了一个尴尬的问题&#xff1a;模型总是把Python代码片段误判为"待办…...

ThreadLocal 源码分析与内存泄漏问题

前言 ThreadLocal 是 Java 中实现线程局部变量的重要工具&#xff0c;被广泛应用于事务管理、链路追踪、用户上下文等场景。然而&#xff0c;面试中关于 ThreadLocal 的追问往往直指其底层设计和内存泄漏问题。 本文将深入分析 ThreadLocal 的源码实现&#xff0c;揭示内存泄…...

Java+AI:让技术概念落地为企业真实业务价值

在大模型技术普及的当下&#xff0c;不少Java技术栈企业完成了大模型的基础接入&#xff0c;但却陷入了“技术空转”的困境——仅实现了简单的API调用&#xff0c;却未能将AI能力与业务流程深度融合&#xff0c;最终让技术探索停留在概念层面。真正的AI价值&#xff0c;从来不是…...

避坑指南:Dify知识库数据清洗的5个常见错误与正则表达式优化技巧

避坑指南&#xff1a;Dify知识库数据清洗的5个常见错误与正则表达式优化技巧 在企业级知识库构建过程中&#xff0c;数据清洗环节往往成为影响LLM问答质量的关键瓶颈。许多团队投入大量资源进行知识库建设后&#xff0c;仍面临"清洗了数据但召回率低"的困境。本文将揭…...

Java 四种安全加载 P12 证书的方案

文章目录从文件绝对路径加载【最常用、最稳定】从 resources 目录加载从 byte [] 字节数组加载从 Base64 字符串加载如果文章对您有用&#xff0c;请关注点赞加收藏&#xff0c;博主会持续更新相关的专栏笔记&#x1fae1; 从文件绝对路径加载【最常用、最稳定】 适合&#xf…...