欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 教育 > 高考 > [Vue3 + TS + Vite]文件选择器-组件

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

2025/9/15 3:09:09 来源:https://blog.csdn.net/qq_45831414/article/details/141271718  浏览:    关键词:[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() 方法

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词