当前位置: 首页 > 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…...

业务系统对接大模型的基础方案:架构设计与关键步骤

业务系统对接大模型&#xff1a;架构设计与关键步骤 在当今数字化转型的浪潮中&#xff0c;大语言模型&#xff08;LLM&#xff09;已成为企业提升业务效率和创新能力的关键技术之一。将大模型集成到业务系统中&#xff0c;不仅可以优化用户体验&#xff0c;还能为业务决策提供…...

设计模式和设计原则回顾

设计模式和设计原则回顾 23种设计模式是设计原则的完美体现,设计原则设计原则是设计模式的理论基石, 设计模式 在经典的设计模式分类中(如《设计模式:可复用面向对象软件的基础》一书中),总共有23种设计模式,分为三大类: 一、创建型模式(5种) 1. 单例模式(Sing…...

CMake 从 GitHub 下载第三方库并使用

有时我们希望直接使用 GitHub 上的开源库,而不想手动下载、编译和安装。 可以利用 CMake 提供的 FetchContent 模块来实现自动下载、构建和链接第三方库。 FetchContent 命令官方文档✅ 示例代码 我们将以 fmt 这个流行的格式化库为例,演示如何: 使用 FetchContent 从 GitH…...

如何理解 IP 数据报中的 TTL?

目录 前言理解 前言 面试灵魂一问&#xff1a;说说对 IP 数据报中 TTL 的理解&#xff1f;我们都知道&#xff0c;IP 数据报由首部和数据两部分组成&#xff0c;首部又分为两部分&#xff1a;固定部分和可变部分&#xff0c;共占 20 字节&#xff0c;而即将讨论的 TTL 就位于首…...

免费PDF转图片工具

免费PDF转图片工具 一款简单易用的PDF转图片工具&#xff0c;可以将PDF文件快速转换为高质量PNG图片。无需安装复杂的软件&#xff0c;也不需要在线上传文件&#xff0c;保护您的隐私。 工具截图 主要特点 &#x1f680; 快速转换&#xff1a;本地转换&#xff0c;无需等待上…...

Vite中定义@软链接

在webpack中可以直接通过符号表示src路径&#xff0c;但是vite中默认不可以。 如何实现&#xff1a; vite中提供了resolve.alias&#xff1a;通过别名在指向一个具体的路径 在vite.config.js中 import { join } from pathexport default defineConfig({plugins: [vue()],//…...

elementUI点击浏览table所选行数据查看文档

项目场景&#xff1a; table按照要求特定的数据变成按钮可以点击 解决方案&#xff1a; <el-table-columnprop"mlname"label"名称"align"center"width"180"><template slot-scope"scope"><el-buttonv-if&qu…...

五子棋测试用例

一.项目背景 1.1 项目简介 传统棋类文化的推广 五子棋是一种古老的棋类游戏&#xff0c;有着深厚的文化底蕴。通过将五子棋制作成网页游戏&#xff0c;可以让更多的人了解和接触到这一传统棋类文化。无论是国内还是国外的玩家&#xff0c;都可以通过网页五子棋感受到东方棋类…...

绕过 Xcode?使用 Appuploader和主流工具实现 iOS 上架自动化

iOS 应用的发布流程一直是开发链路中最“苹果味”的环节&#xff1a;强依赖 Xcode、必须使用 macOS、各种证书和描述文件配置……对很多跨平台开发者来说&#xff0c;这一套流程并不友好。 特别是当你的项目主要在 Windows 或 Linux 下开发&#xff08;例如 Flutter、React Na…...

32位寻址与64位寻址

32位寻址与64位寻址 32位寻址是什么&#xff1f; 32位寻址是指计算机的CPU、内存或总线系统使用32位二进制数来标识和访问内存中的存储单元&#xff08;地址&#xff09;&#xff0c;其核心含义与能力如下&#xff1a; 1. 核心定义 地址位宽&#xff1a;CPU或内存控制器用32位…...