近期表单写的比较多,设计到上传图片和上传文件,总结了一下,一起分享
主要功能
- 限制图片数量
- 限制图片宽高
- 上传按钮展示/隐藏
父组件主要代码
html代码
<UploadImage
ref="uploadImageRef"
:limit-image-info="limitImageInfo"
@uploadImage="uploadImage"
></UploadImage>
js代码
<script setup>
import { ref } from 'vue'
import { UploadImage } from '@/widgets/index.js' //子组件路径
// 图片操作
const limitImageInfo = ref({
maxWidth: 820,//上传图片最大宽度
maxHeight: 608,//上传图片最大高度
imageNum: 5,//上传图片最大数量
limitImageSize: true,//是否限制图片宽高
})
const uploadImageRef = ref(null)//稍后再看这个的作用
let picListArr = ref([])//子组件返回的数据,主要用于父组件里前端和后端交互使用
const uploadImage = (e) => {
picListArr.value = e
}
</script>
子组件主要代码
html代码
isShowUpload:上传按钮显示状态
handleUploadImage:上传事件
delImage:删除事件
<template>
<div class="upload-license-left">
<div v-if="isShowUpload" class="left-images left-images-up">
<div class="left-images-input">
<input
id="uploadimage"
type="file"
accept="image/png, image/jpeg, image/jpg"
@change="handleUploadImage"
/>
</div>
</div>
<template v-if="pic.length">
<div v-for="(item, index) in pic" :key="index" class="left-images-img">
<img :src="item" alt="" />
<img
class="close-btn"
src="@/pages/qyneed/need-fill/images/close.png"
alt=""
@click="delImage(index)"
/>
</div>
</template>
</div>
</template>
js代码
<script setup>
import { ref, computed, watch } from 'vue'
import { DialogModel } from '@/components' //封装的弹窗组件,这里不再展示
import { limitImageSize } from './help' //上传图片的限制条件
const { fetchPicUpload } = FileHandle() //图片的处理逻辑
const props = defineProps({
//父组件传递的参数
limitImageInfo: {
type: Object,
default: () => {
return {}
},
},
})
const tempValue = ref(props.limitImageInfo)
//如果不computed传递的数据是空
const showLimitImageInfo = computed(() => {
return tempValue.value
})
// eslint-disable-next-line no-console
console.log(showLimitImageInfo.value)
// 上传图片
let pic = ref([])
let picListArr = ref([])
const emits = defineEmits(['uploadImage'])
const handleUploadImage = async (e) => {
showLimitImageInfo.value.limitImageSize &&
(await limitImageSize(
e,
showLimitImageInfo.value.maxWidth,
showLimitImageInfo.value.maxHeight
))
if (picListArr.value.length >= showLimitImageInfo.value.imageNum) {
DialogModel({
message: `最多可以添加${showLimitImageInfo.value.imageNum}张图片!`,
cancelable: false,
confirm: fialComfilmBtn,
})
} else {
const file = e.target.files[0]
let picObj = await fetchPicUpload(file)
if (picObj) {
pic.value.push(fileToDataurl(file))
picListArr.value.push(picObj.path)
}
}
emits('uploadImage', picListArr.value)
}
// 文件转化成url
const fileToDataurl = (file) => {
return URL.createObjectURL(file)
}
// 删除图片
const delImage = (index) => {
pic.value.splice(index, 1)
picListArr.value.splice(index, 1)
}
//vue3将变量导出,供父组件使用
defineExpose({
pic,
})
const isShowUpload = ref(true)
watch(
() => picListArr.value,
() => {
if (picListArr.value.length >= showLimitImageInfo.value.imageNum) {
isShowUpload.value = false
} else {
isShowUpload.value = true
}
},
{ deep: true }
)
const fialComfilmBtn = () => {}
</script>
css主要代码
<style scoped>
#uploadimage {
height: 100%;
cursor: pointer;
}
.upload-license-left {
display: flex;
flex-wrap: wrap;
}
.left-images-up {
width: 120px;
height: 120px;
background-image: url('@/pages/qyneed/need-fill/images/uploadIcon.png');
background-size: 100% 100%;
/* margin-bottom: 20px; */
margin-right: 20px;
}
.left-images-input {
width: 100%;
height: 100%;
position: relative;
}
.left-images-input input {
width: 100%;
height: 100%;
cursor: pointer;
opacity: 0;
}
.left-images-img {
width: 120px;
height: 120px;
background: #f2f2f2;
position: relative;
margin-right: 20px;
margin-bottom: 20px;
}
.left-images-img img:first-child {
width: 120px;
height: 120px;
position: absolute;
top: 0;
left: 0;
border-radius: 10px;
}
.left-images-img img.close-btn {
width: 24px;
height: 24px;
position: absolute;
top: -12px;
right: -12px;
cursor: pointer;
}
</style>
help.js里limitImageSize 方法
import { DialogModel } from '@/components/index.js'
let limitImageSize = (e, width, height) => {
return new Promise((resolve, reject) => {
let url = window.URL || window.webkitURL
let img = new Image()
img.src = url.createObjectURL(e.target.files[0])
let status = 0
img.onload = () => {
if (img.width > width) {
DialogModel({
message: `图片宽度不能超过${width}`,
cancelable: false,
confirm: fialComfilmBtn,
})
reject(false)
} else if (img.height > height) {
DialogModel({
message: `图片高度不能超过${height}`,
cancelable: false,
confirm: fialComfilmBtn,
})
reject(false)
} else {
resolve(true)
}
}
})
}
const fialComfilmBtn = () => {}
export { limitImageSize }
上传文件及文件格式快速通道