以下是基于 vant-ui
(适配 Vue2 版本 )实现截图中照片上传预览、删除功能,并封装成可复用组件的完整代码,包含样式和逻辑实现,可直接在 Vue2 项目中使用:
1. 封装的图片上传组件 ImageUploader.vue
<template>
<div class="image-uploader-container">
<div class="upload-title">照片</div>
<van-uploader
v-model="fileList"
:max-count="9"
:after-read="handleAfterRead"
:before-delete="handleBeforeDelete"
upload-text="添加图片"
:preview-size="80"
preview-image
class="uploader-wrapper"
>
<!-- 自定义添加图片的默认插槽内容,模拟截图样式 -->
<template #default>
<div class="custom-upload-btn">
<van-icon name="photograph" size="32" color="#999" />
<div class="upload-tip">添加图片</div>
</div>
</template>
</van-uploader>
</div>
</template>
<script>
import { Uploader, Icon } from 'vant';
import 'vant/lib/index.css';
export default {
name: 'ImageUploader',
components: {
vanUploader: Uploader,
vanIcon: Icon
},
data() {
return {
fileList: []
};
},
methods: {
// 图片上传成功回调
handleAfterRead(file) {
// vant 的 after-read 会返回文件对象,需转成 vant 要求的 fileList 格式
const newFile = {
url: file.content,
// 可扩展其他属性,比如文件名称等
name: file.file.name
};
this.fileList.push(newFile);
},
// 删除图片前的回调,用于确认删除逻辑(也可直接返回 true 直接删除)
handleBeforeDelete(file, index) {
// 这里可加删除确认逻辑,比如弹出提示框
return true;
}
}
};
</script>
<style scoped>
.image-uploader-container {
border: 1px solid #409eff;
border-radius: 4px;
padding: 10px;
}
.upload-title {
font-size: 16px;
color: #333;
margin-bottom: 10px;
}
.uploader-wrapper {
display: flex;
flex-wrap: wrap;
gap: 10px;
}
/* 自定义添加按钮样式 */
.custom-upload-btn {
width: 80px;
height: 80px;
border: 1px dashed #ccc;
border-radius: 4px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
color: #999;
cursor: pointer;
}
.upload-tip {
margin-top: 4px;
font-size: 12px;
}
/* 调整上传后图片预览样式,让删除按钮位置更贴近截图 */
.van-uploader__preview {
position: relative;
}
.van-uploader__preview-delete {
position: absolute;
top: -6px;
right: -6px;
background-color: rgba(0, 0, 0, 0.7);
border-radius: 50%;
padding: 2px 6px;
color: #fff;
font-size: 12px;
}
</style>
2. 组件使用示例(在其他页面中引入 )
<template>
<div class="page-container">
<h2>示例页面</h2>
<ImageUploader />
</div>
</template>
<script>
import ImageUploader from './ImageUploader.vue';
export default {
name: 'ExamplePage',
components: {
ImageUploader
}
};
</script>
<style scoped>
.page-container {
padding: 20px;
}
</style>
代码功能拆解与说明
1. 基础功能实现
- 组件引入与注册:从
vant
中引入Uploader
(上传组件 )和Icon
(图标组件 ),并在当前组件中注册,同时引入vant
的基础样式文件vant/lib/index.css
(若项目已全局引入vant
样式,可省略 )。 van-uploader
配置:v-model="fileList"
:双向绑定已上传图片列表数据,用于展示已上传的图片。:max-count="9"
:限制最多可上传 9 张图片,可根据需求调整。:after-read="handleAfterRead"
:图片上传成功(读取完成 )后的回调函数,用于将上传的文件处理后加入fileList
展示。:before-delete="handleBeforeDelete"
:删除图片前的回调,可在这里加删除确认逻辑,示例中直接返回true
允许删除,实际项目可结合van-dialog
等组件做确认提示。upload-text="添加图片"
:默认上传按钮的文本,不过这里用了自定义插槽覆盖,所以该属性实际作用不大,主要是配合组件逻辑。:preview-size="80"
:设置预览图片的尺寸,单位为px
,和截图中图片大小适配。preview-image
:开启图片预览功能,点击已上传图片可查看大图。
- 自定义添加按钮:通过
#default
插槽,自定义“添加图片”的显示样式,用van-icon
展示相机图标,下方加文字提示,模拟截图中的样式。
2. 样式适配
- 容器与标题:给组件最外层容器加蓝色边框和圆角,设置标题样式,贴近截图布局。
- 自定义添加按钮:设置添加按钮的宽高、边框样式(虚线 )、图标和文字样式,模拟截图中“添加图片”区域的外观。
- 预览图片与删除按钮:调整
vant
上传后预览图片的样式,让删除按钮(van-uploader__preview-delete
)位置更贴近截图,通过绝对定位放到图片右上角,优化显示效果。
3. 功能扩展点
- 图片上传逻辑:当前
handleAfterRead
只是简单将文件转成fileList
格式展示,实际项目中,通常需要结合后端接口,把文件真正上传到服务器,可修改handleAfterRead
方法,调用接口上传文件,成功后再把服务器返回的图片地址存入fileList
,示例如下:
handleAfterRead(file) {
// 假设 uploadFileToServer 是调用后端接口上传文件的方法,返回 Promise
uploadFileToServer(file.file).then((res) => {
const newFile = {
url: res.data.imageUrl,
name: file.file.name
};
this.fileList.push(newFile);
}).catch((err) => {
console.error('上传失败:', err);
// 可在这里提示用户上传失败
});
}
- 删除逻辑增强:若要实现删除图片时同时调用后端接口删除服务器上的文件,可在
handleBeforeDelete
中发起接口请求,成功后再返回true
删除前端列表数据,示例:
handleBeforeDelete(file, index) {
return new Promise((resolve, reject) => {
// 假设 deleteFileFromServer 是调用后端删除接口的方法,入参是图片地址等
deleteFileFromServer(file.url).then(() => {
resolve(true);
}).catch((err) => {
console.error('删除失败:', err);
reject(false);
});
});
}
- 图片尺寸限制与裁剪:如果需要限制上传图片的尺寸、进行裁剪等操作,可结合
vant
的Uploader
组件的before-read
钩子,在图片读取前进行处理,比如使用canvas
裁剪图片,或者判断图片尺寸不符合要求时提示用户重新选择。
这样就完整实现了截图中照片上传、预览、删除的功能,并封装成了可复用的 Vue2 组件,方便在其他页面中通过简单引入即可使用,后续还能根据实际业务需求进一步扩展和优化 。