赞
踩
实现功能:
1、封装el-upload组件,父组件可以控制图片上传框的宽高
2、父组件可以传入提示信息,利用具名插槽
3、上传前的校验
4、实现删除功能
不同配置下的效果:
下边案例是图片上传的时候没有掉接口,在整体提交的时候才调用的接口,所以需要一个中间变量去接收他的图片回显
父组件引用:
<script setup lang="ts"> import { ref } from 'vue' import { useUserStore } from '@/stores'; const userStore = useUserStore() const img = ref(userStore.user.user_pic) const selectRef = ref(null) //1、调用el-upload中on-change事件 // const triggerChange = ()=>{ // if(selectRef.value){ // const file = new File ([""],"filename") // selectRef.value.onSelectFile(file,[]) // } // } //2、点击按钮调用子组件,图片上传选择文件弹出框 const openFileDialog =()=>{ selectRef.value.$refs.uploadRef.$el.querySelector('input').click() } </script> <template> <pageContainer title="更换头像"> <uploadImg v-model="img" ref="selectRef" width="200px" height="200px" line-height="200px" > <!-- 具名插槽 --> <template #tips> <div style="margin-top:10px;"> <el-button type="primary" size="small" @click="openFileDialog">更换头像</el-button> <el-button type="success" size="small" >上传头像</el-button> </div> </template> </uploadImg> </pageContainer> </template> <style scoped> </style>
子组件:
<script setup lang="ts"> import { ref } from 'vue' import { ElMessage } from 'element-plus' import { Plus,Close } from '@element-plus/icons-vue' const imageUrl = ref('') const props = defineProps({ modelValue:{ type:String }, width:{ type:String, default: '180px' }, height:{ type:String, default: '180px' }, lineHeight:{ type:String, default: '180px' } }) const uploadRef = ref() // 1、不是在上传的时候调接口而是本地上传,提交表单时再调取接口 // 所以再没有数据的时候并且modelValue传过来的是一个空对象的时候要将图片回显置空 const handleImg = ()=>{ imageUrl.value=props.modelValue if(JSON.stringify(imageUrl.value) == "{}"){ imageUrl.value='' } } handleImg() const emit =defineEmits(['update:modelValue']) const onSelectFile = (uploadFile) => { //2、上传前校验 const imgType = ['image/png','image/jpeg', 'image/gif', 'image/bmp', 'image/jpg'] const isLt5M = uploadFile.raw.size/1024/1024 < 2 if(!imgType.includes(uploadFile.raw.type)){ return ElMessage.error('请上传正确的图片格式') } if(!isLt5M){ return ElMessage.error('上传的图片太大了') } //3、转成在线地址实现预览 imageUrl.value = URL.createObjectURL(uploadFile.raw) //4、改变父组件的值 emit('update:modelValue',uploadFile.raw) } defineExpose({ onSelectFile, }) //删除图片 const deleteImg = ()=>{ imageUrl.value = '' emit('update:modelValue','') } </script> <template> //1、此处关闭自动上传,:auto-upload="false" //2、不需要action,本地上传,提交时再上传图片 //3、URL.createObjectURL(...)创建本地预览的地址,此处只本地预览,点击提交的时候,再整个form调接口。 //4、如果上传图片的时候就调接口,用:http-request="uploadImgage" //5、如果有:auto-upload="false" 属性就要用:on-change 方法监听 const uploadImgage = async(file) => { // 请求接口中需要带url以及 let result = await proxy.Request({ url:api.uploadUrl, // 上传路径 dataType:'file', // 指定传输类型 params:{ file:file.file, // 提交上传路径到指定位置 type:0, } }) const fileName = result.data.fileName emit('update:modelValue',fileName) }; <div class="imgContent" :style="{'width':width,'height':height}"> <el-upload class="avatar-uploader" :show-file-list="false" :auto-upload="false" :on-change="onSelectFile" ref="uploadRef" > <img v-if="imageUrl" :src="imageUrl" class="avatar" :style="{'width':width,'height':height}"/> <el-icon v-else class="avatar-uploader-icon" :style="{'width':width,'height':height,'line-height':lineHeight}"><Plus /></el-icon> </el-upload> <div v-if="imageUrl" class="delete" @click="deleteImg"> <el-icon><Close /></el-icon> </div> </div> <slot name="tips">默认内容</slot> </template> <style scoped lang="scss"> .imgContent{ position: relative; &:hover .delete{ display:block; } } .delete{ position: absolute; display: none; width:20px; height:20px; top:-8px; left:-8px; background-color: red; border-radius: 50%; text-align: center; line-height: 24px; } .el-icon{ color:#fff; font-weight: 700; } .avatar-uploader .avatar { width: 178px; height: 178px; display: block; } </style> <style> .avatar-uploader .el-upload { border: 1px dashed var(--el-border-color); border-radius: 6px; cursor: pointer; position: relative; overflow: hidden; transition: var(--el-transition-duration-fast); } .avatar-uploader .el-upload:hover { border-color: var(--el-color-primary); } .el-icon.avatar-uploader-icon { font-size: 28px; color: #8c939d; width: 178px; height: 178px; text-align: center; } </style>
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。