基于Vue3 Composition API实现全局文件上传组件并获取base64格式imageUrl
实现全局可用的图片选择组件方案
分两种常用实现方式,按需选择即可:
方案1:全局注册带预览的组件(适合需要在页面显示选择按钮+预览图的场景)
第一步:改造现有组件为可复用组件
新建src/components/BaseImagePicker.vue,替换为以下修正后的代码(解决原代码setup中错误使用this的问题,新增双向绑定支持):
<template> <div class="column" style="width: 300px;"> <q-btn @click="sendEventImage" style="margin-top: 16px; margin-bottom: 32px;" outline color="white" text-color="black" label="选择图片" /> <input style="display:none" ref="EventfileInput" @change="onEventFilePicked" type="file" name="upload" accept="image/*" /> <q-img v-if="imageUrl" class="w-30 h-30" :src="imageUrl" /> </div> </template> <script setup> import { ref } from 'vue' // 双向绑定配置,Vue3.4+支持defineModel,低版本可替换为props+emit const modelValue = defineModel() const imageUrl = ref(modelValue.value || '') const EventfileInput = ref(null) const sendEventImage = () => { console.log('触发图片选择') EventfileInput.value.click() } const onEventFilePicked = (event) => { const files = event.target.files if (!files.length) return const image = files[0] const filename = image.name if (filename.lastIndexOf('.') <= 0) { return alert('请添加有效的图片文件') } const fileReader = new FileReader() fileReader.addEventListener('load', () => { imageUrl.value = fileReader.result // 同步值到父组件 modelValue.value = fileReader.result // 重置input,避免重复选择同一文件不触发change事件 EventfileInput.value.value = '' }) fileReader.readAsDataURL(image) } </script>
第二步:全局注册组件
在项目入口文件src/main.js中添加注册逻辑:
import { createApp } from 'vue' import App from './App.vue' import BaseImagePicker from './components/BaseImagePicker.vue' const app = createApp(App) // 全局注册组件,所有页面无需导入直接使用 app.component('BaseImagePicker', BaseImagePicker) app.mount('#app')
第三步:任意业务组件中调用并获取base64
在setup中直接绑定变量即可使用:
<template> <div> <!-- 直接使用全局组件,双向绑定获取base64 --> <BaseImagePicker v-model="uploadImage" /> <q-btn @click="handleUpload" label="上传图片" /> </div> </template> <script setup> import { ref } from 'vue' // 存储选择后的base64图片 const uploadImage = ref('') const handleUpload = () => { if (!uploadImage.value) return alert('请先选择图片') // 直接拿到base64做后续上传逻辑 console.log('待上传的base64:', uploadImage.value) // 调用上传接口... } </script>
方案2:全局方法调用(适合无需显示预览,直接唤起选择框的场景)
如果不需要在页面显示选择按钮和预览,只需要调用方法就能选图拿base64,可以封装成全局工具方法:
第一步:封装选择逻辑为工具函数
新建src/utils/imagePicker.js:
export const pickImage = () => { return new Promise((resolve, reject) => { const input = document.createElement('input') input.type = 'file' input.accept = 'image/*' input.style.display = 'none' input.onchange = (e) => { const file = e.target.files[0] if (!file) return reject('未选择文件') if (file.name.lastIndexOf('.') <= 0) { return reject('无效的图片文件') } const reader = new FileReader() reader.onload = () => { document.body.removeChild(input) resolve(reader.result) } reader.onerror = () => { document.body.removeChild(input) reject('文件读取失败') } reader.readAsDataURL(file) } input.oncancel = () => { document.body.removeChild(input) reject('用户取消选择') } document.body.appendChild(input) input.click() }) }
第二步:全局挂载(可选)
如果要在所有组件的setup里直接用,也可以挂载到全局,或者直接按需导入:
// main.js中添加 import { pickImage } from './utils/imagePicker' app.config.globalProperties.$pickImage = pickImage // 也可以直接在业务组件中导入使用
第三步:调用示例
// 业务组件setup中使用 const handleSelectImage = async () => { try { const imageBase64 = await pickImage() // 直接拿到base64做上传 console.log('选择的图片base64:', imageBase64) } catch (err) { console.log(err) alert(err) } }
内容的提问来源于stack exchange,提问作者eeerrrttt
相关产品推荐
相关产品推荐

