记录———封装uni-app+vant(u-upload)上传图片组件
上传图片回显,自定义图片回显样式
这段代码是一个Vue组件,主要实现了图片上传和预览的功能。组件接收了父组件传递的图片列表、最大图片数量和上传状态等属性。在模板中,使用了uni-easyinput
组件和u-upload
组件来实现图片上传和预览功能。在方法中,实现了删除图片、上传图片和预览图片的逻辑。整体功能包括图片上传、预览、删除和限制最大图片数量等。
父组件使用:
parentImgList
中传入的值双向,子组件更新则父组件更新,是图片URL数组
isUploading
是当前是否正在上传中
<upload-image :parentImgList.sync="form.imgList" :isUploading.sync="isUploading"></upload-image>
组件内容
<template>
<view>
<view class="photo-box flex-row">
<view class="photo" v-for="(item, index) in imgList" :key="index">
<view class="delete-btn" @click="deletePhoto(index, 'after')">
<img src="@/assets/icon/delete.svg" />
</view>
<view class="photo-image" @click="viewImage(item)">
<img :src="item" />
</view>
</view>
<!-- v-bind="$attrs" 接收父组件的传值,并赋给<u-upload>;
某一属性如果子组件(本组件)已经设值,子组件的值覆盖父组件的;
以maxCount属性为例,这里设了5,那么不管父组件传多少,实际用的值一直是5。 -->
<u-upload
v-bind="$attrs"
:maxCount="maxCount"
name="fileList"
uploadIcon="plus"
width="110"
height="110"
:previewFullImage="true"
multiple
@afterRead="handleAfterRead"
@delete="deletePic"
v-if="!isUpload && imgList.length < 6"
>
<view class="upload-content">
<u-icon name="plus" color="#6E9CFE" size="20"></u-icon>
</view>
</u-upload>
<view class="upload-content" v-if="isUpload && imgList.length < 6">{{ isUpload }}</view>
</view>
<view style="color: #999;font-size: 9px;margin-top: 2px;">最多上传六张</view>
<!-- 模态框显示大图 -->
<view v-if="showModal" class="modal" @click="showModal = false">
<img :src="currentImage" class="modal-image" />
</view>
<van-overlay :show="isUploading">
<van-loading size="35px">图片上传中...</van-loading>
</van-overlay>
</view>
</template>
<script>
import { photoUploadFileAPI } from "@/api/upload.js"; // 与后端商量好的上传图片接口,使用 uni.uploadFile
import { Loading, Notify } from 'vant-green'; // vant的组件
export default {
name: "img-upload",
props: {
parentImgList: {
type: Array,
default: () => {
return [];
},
},
maxCount: {
type: Number,
default: 6,
},
isUploading: {
type: Boolean,
default: false
}
},
data() {
return {
fileList: [],
imgList: [],
showModal: false,
currentImage: "",
isUpload: '',
chooseImgNumber: 0
};
},
watch: {
parentImgList: {
handler(val) {
// console.log("父组件传递的数据", val);
if (val) {
this.imgList = val;
}
},
deep: true,
},
imgList(val) {
// console.log("女此案你看见", val);
this.$emit("update:parentImgList", val);
},
},
mounted() {
console.log("fileList", this.value);
},
methods: {
// s删除修改状态下原本有的照片
deletePhoto(index) {
this.imgList.splice(index, 1);
console.log(`点击删除序号为${index}的照片`, this.imgList);
},
// 新增图片
async handleAfterRead(event) {
// 当设置 mutiple 为 true 时, file 为数组格式,否则为对象格式
this.chooseImgNumber++
this.$emit('update:isUploading', true)
let lists = [].concat(event.file);
console.log('上传的图片', lists, lists.length, event.file)
this.isUpload = '上传中...'
for (let i = 0; i < lists.length; i++) {
if (this.imgList.length < 6) {
const result = await photoUploadFileAPI(lists[i].url);
console.log("result>>>图片上传结果", result);
if (result.success) {
this.imgList.push(result.data);
this.chooseImgNumber--
} else {
Notify({ type: 'danger', message: '图片上传失败' });
}
} else {
Notify({ type: 'warning', message: '最多上传6张图片' })
}
}
this.isUpload = ''
this.$emit('update:isUploading', false)
// console.log("fileList2", this.fileList, this.imgList, this.chooseImgNumber);
// this.$emit('input', this.imgList);
},
viewImage(image) {
this.currentImage = image;
this.showModal = true;
},
},
};
</script>
<style lang="scss" scoped>
.photo-box {
margin-right: 10px;
flex-wrap: wrap;
.photo {
position: relative;
.photo-image {
width: 95px;
height: 95px;
margin-right: 10px;
margin-bottom: 5px;
img {
width: 100%;
/* 使图片宽度填满容器 */
height: 100%;
/* 使图片高度填满容器 */
object-fit: cover;
/* 保持比例并裁剪 */
border-radius: 4px;
}
}
.delete-btn {
position: absolute;
right: 8px;
top: 0;
background-color: rgba($color: #000000, $alpha: 0.1);
width: 18px;
border-radius: 20px;
height: 18px;
// font-size: 40rpx;
text-align: center;
// line-height: 50rpx;
color: #555;
}
}
}
.modal {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.8);
display: flex;
justify-content: center;
align-items: center;
z-index: 99999999999;
}
.modal-image {
max-width: 90%;
max-height: 90%;
}
.upload-content {
display: flex;
justify-content: center;
align-items: center;
width: 100px;
height: 102px;
border-radius: 3px;
margin-top: 1px;
border: 1px dashed #5a9fff;
// background: #f4f8ff;
box-sizing: border-box;
}
</style>
<style>
.van-loading, .van-loading__spinner {
/* margin-top: 45%; */
}
.van-overlay {
padding-top: 45vh;
text-align: center;
}
</style>