代码实现:
<template>
<div class="image-uploader">
<div v-for="(image, index) in images" :key="index" class="image-preview">
<img :src="image" alt="Preview" />
<button @click="deleteImage(index)">Delete</button>
</div>
<div class="image-upload">
<label>
<input type="file" @change="uploadImage" />
<span>+</span>
</label>
</div>
</div>
</template>
<script>
export default {
data() {
return {
images: []
};
},
methods: {
uploadImage(event) {
const files = event.target.files;
for (let i = 0; i < files.length && this.images.length < 9; i++) {
const reader = new FileReader();
reader.readAsDataURL(files[i]);
reader.onload = () => {
this.images.push(reader.result);
};
}
},
deleteImage(index) {
this.images.splice(index, 1);
}
}
};
</script>
<style scoped>
.image-uploader {
display: flex;
flex-wrap: wrap;
justify-content: center;
}
.image-preview {
position: relative;
margin: 10px;
width: 150px;
height: 150px;
}
.image-preview img {
width: 100%;
height: 100%;
object-fit: cover;
}
.image-preview button {
position: absolute;
top: 5px;
right: 5px;
padding: 5px;
border: none;
background-color: rgba(255, 255, 255, 0.8);
color: #f00;
}
.image-upload {
position: relative;
margin: 10px;
width: 150px;
height: 150px;
background-color: #eee;
display: flex;
justify-content: center;
align-items: center;
}
.image-upload label {
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
font-size: 48px;
color: #999;
transition: all 0.3s;
}
.image-upload label:hover {
background-color: rgba(255, 255, 255, 0.8);
}
.image-upload label span {
margin-top: -10px;
}
.image-upload input[type="file"] {
display: none;
}
</style>
思路:
组件中使用了一个images
数组来保存上传的图片,uploadImage
方法用来添加图片,deleteImage
方法用来删除图片。组件中展示的图片预览和删除按钮都是通过v-for
指令遍历images
数组生成的。
为了保证最多只能上传九张图片,uploadImage
方法中添加了一个判断,当images
数组中的元素个数达到了九个或者文件列表中的文件已经全部添加完毕时,上传操作就会停止。同时,在HTML中也限制了只能添加一个文件的输入框。
组件的样式采用了flex布局,并使用了CSS3的过渡效果来增强