下面我将详细讲解“vue封装组件之上传图片组件”的完整攻略。
1. 简介
上传图片组件是Web开发中常用的组件之一,因此我们也需要封装一个通用的上传图片组件供其他开发者使用。本文将使用Vue.js框架,并结合element-ui组件库,来实现上传图片组件的封装。
2. 基本结构
上传图片组件需要包含以下基本结构:
- 文件上传的表单项
- 上传进度条
- 预览已上传图片
- 删除已上传图片按钮
- 上传图片按钮
具体结构代码如下:
<template>
<div>
<!-- 文件上传表单项 -->
<el-upload
class="upload-file"
:action="uploadUrl"
:show-file-list="false"
:data="formData"
:on-success="handleSuccess"
:before-upload="beforeUpload"
:on-progress="handleProgress"
ref="upload"
>
<!-- 上传图片按钮 -->
<el-button
size="medium"
type="primary"
:disabled="disabled"
>
<slot name="upload-btn">上传图片</slot>
</el-button>
<!-- 上传进度条 -->
<el-progress
class="upload-progress"
:percentage="uploadPercentage"
:stroke-width="2"
:color="customColor"
:hide-info="true"
:show-text="false"
:status="status"
></el-progress>
</el-upload>
<!-- 上传成功的图片预览及删除按钮 -->
<div class="view-file-list" v-if="fileList && fileList.length > 0">
<el-card
shadow="hover"
v-for="(file, index) in fileList"
:key="index"
class="view-card"
>
<img
:src="file.url || file.preview"
class="view-img"
/>
<el-button
size="small"
type="danger"
class="delete-btn"
icon="el-icon-delete"
@click.prevent="handleDelete(index)"
></el-button>
</el-card>
</div>
</div>
</template>
<script>
export default {
name: 'UploadImage',
props: {
uploadUrl: {
type: String,
required: true
},
formData: {
type: Object,
default: () => ({})
},
disabled: {
type: Boolean,
default: false
},
customColor: {
type: String,
default: ''
},
fileSizeLimit: {
type: Number,
default: 2
},
fileTypeLimit: {
type: Array,
default: () => ['jpg', 'jpeg', 'png', 'gif']
}
},
data() {
return {
fileList: [],
uploadPercentage: 0,
status: 'warning'
}
},
methods: {
beforeUpload(file) {
const isLtSize = file.size / 1024 / 1024 < this.fileSizeLimit
const fileTypeArr = file.name.split('.')
const fileType = fileTypeArr[fileTypeArr.length - 1].toLowerCase()
const isFileType = this.fileTypeLimit.includes(fileType)
if (!isLtSize) {
this.$message.error(`上传图片不能超过 ${this.fileSizeLimit}MB!`)
return false
}
if (!isFileType) {
this.$message.error('上传图片格式必须是' + this.fileTypeLimit.join('、'))
return false
}
return true
},
handleSuccess(response, file, fileList) {
if (response.code !== '0') {
this.$message.error('上传失败')
return
}
const { data } = response
if (data && data.length > 0) {
this.fileList.push({
url: data[0].url,
name: file.name
})
this.status = 'success'
}
},
handleProgress(event, file, fileList) {
this.uploadPercentage = Math.floor(event.percent)
},
handleDelete(index) {
this.fileList.splice(index, 1)
this.$refs.upload.clearFiles()
this.uploadPercentage = 0
this.status = 'warning'
}
},
watch: {
fileList: {
handler(val) {
this.$emit('update:fileList', val)
},
deep: true
}
}
}
</script>
<style scoped>
.upload-file {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
width: 180px;
height: 180px;
margin-bottom: 20px;
border: 1px dashed #d9d9d9;
border-radius: 2px;
}
.view-file-list {
display: flex;
flex-wrap: wrap;
margin-top: 10px;
margin-bottom: 10px;
}
.view-card {
display: flex;
justify-content: center;
align-items: center;
margin-right: 10px;
margin-bottom: 10px;
width: 180px;
height: 180px;
}
.view-img {
max-width: 100%;
max-height: 100%;
border-radius: 2px;
}
.delete-btn {
position: absolute;
top: 5px;
right: 5px;
}
</style>
3. 基本使用
使用上传图片组件,只需要在Vue实例中引入该组件,并传入必要的参数即可。
<template>
<div>
<upload-image
:upload-url="uploadUrl"
:form-data="formData"
:disabled="disabled"
:file-size-limit="fileSizeLimit"
:file-type-limit="fileTypeLimit"
:custom-color="customColor"
v-model="fileList"
>
<template #upload-btn>
<i class="el-icon-plus"></i>
上传
</template>
</upload-image>
</div>
</template>
<script>
import UploadImage from '@/components/UploadImage'
export default {
name: 'Example',
components: {
UploadImage
},
data() {
return {
uploadUrl: '/upload/image',
formData: {
userid: '0001'
},
disabled: false,
fileList: [],
fileSizeLimit: 5,
fileTypeLimit: ['jpg', 'jpeg', 'png', 'gif'],
customColor: '#409eff'
}
}
}
</script>
该示例演示了上传图片组件的基本使用方法,此时我们便可以在页面上看到一个上传按钮,同时也可以预览已上传的图片。
4. 示例说明
实现多图上传
在上面的组件基础上,我们可以使用el-upload
组件的multiple
属性,来实现多张图片上传。
<template>
<div>
<el-upload
class="upload-file"
:action="uploadUrl"
:show-file-list="false"
:data="formData"
:on-success="handleSuccess"
:before-upload="beforeUpload"
:on-progress="handleProgress"
:multiple="true"
ref="upload"
>
<el-button
size="medium"
type="primary"
:disabled="disabled"
>
<slot name="upload-btn">上传图片</slot>
</el-button>
<el-progress
class="upload-progress"
:percentage="uploadPercentage"
:stroke-width="2"
:color="customColor"
:hide-info="true"
:show-text="false"
:status="status"
></el-progress>
</el-upload>
<div class="view-file-list" v-if="fileList && fileList.length > 0">
<el-card
shadow="hover"
v-for="(file, index) in fileList"
:key="file.url + index"
class="view-card"
>
<img
:src="file.url || file.preview"
class="view-img"
/>
<el-button
size="small"
type="danger"
class="delete-btn"
icon="el-icon-delete"
@click.prevent="handleDelete(index)"
></el-button>
</el-card>
</div>
</div>
</template>
<script>
export default {
name: 'UploadImage',
props: {
uploadUrl: {
type: String,
required: true
},
formData: {
type: Object,
default: () => ({})
},
disabled: {
type: Boolean,
default: false
},
customColor: {
type: String,
default: ''
},
fileSizeLimit: {
type: Number,
default: 2
},
fileTypeLimit: {
type: Array,
default: () => ['jpg', 'jpeg', 'png', 'gif']
}
},
data() {
return {
fileList: [],
uploadPercentage: 0,
status: 'warning'
}
},
methods: {
beforeUpload(file) {
const isLtSize = file.size / 1024 / 1024 < this.fileSizeLimit
const fileTypeArr = file.name.split('.')
const fileType = fileTypeArr[fileTypeArr.length - 1].toLowerCase()
const isFileType = this.fileTypeLimit.includes(fileType)
if (!isLtSize) {
this.$message.error(`上传图片不能超过 ${this.fileSizeLimit}MB!`)
return false
}
if (!isFileType) {
this.$message.error('上传图片格式必须是' + this.fileTypeLimit.join('、'))
return false
}
return true
},
handleSuccess(response, file, fileList) {
if (response.code !== '0') {
this.$message.error('上传失败')
return
}
const { data } = response
if (data && data.length > 0) {
data.forEach(item => {
this.fileList.push({
url: item.url,
name: item.name
})
})
this.status = 'success'
}
},
handleProgress(event, file, fileList) {
this.uploadPercentage = Math.floor(event.percent)
},
handleDelete(index) {
this.fileList.splice(index, 1)
this.$refs.upload.clearFiles()
this.uploadPercentage = 0
this.status = 'warning'
}
},
watch: {
fileList: {
handler(val) {
this.$emit('update:fileList', val)
},
deep: true
}
}
}
</script>
上述代码可以实现多张图片上传,预览已上传的多张图片,并提供删除功能。
自定义上传按钮
通过在上传图片组件内部增加一个插槽,我们可以实现上传按钮的样式自定义。下面的示例中,使用element-ui中的icon组件来渲染一个带图标的自定义上传按钮。
<template>
<div>
<el-upload
class="upload-file"
:action="uploadUrl"
:show-file-list="false"
:data="formData"
:on-success="handleSuccess"
:before-upload="beforeUpload"
:on-progress="handleProgress"
:multiple="true"
ref="upload"
>
<slot name="upload-btn">
<el-button
size="medium"
type="primary"
:disabled="disabled"
>
<i class="el-icon-plus"></i>
上传图片
</el-button>
</slot>
<el-progress
class="upload-progress"
:percentage="uploadPercentage"
:stroke-width="2"
:color="customColor"
:hide-info="true"
:show-text="false"
:status="status"
></el-progress>
</el-upload>
<div class="view-file-list" v-if="fileList && fileList.length > 0">
<el-card
shadow="hover"
v-for="(file, index) in fileList"
:key="file.url + index"
class="view-card"
>
<img
:src="file.url || file.preview"
class="view-img"
/>
<el-button
size="small"
type="danger"
class="delete-btn"
icon="el-icon-delete"
@click.prevent="handleDelete(index)"
></el-button>
</el-card>
</div>
</div>
</template>
<script>
export default {
name: 'UploadImage',
props: {
uploadUrl: {
type: String,
required: true
},
formData: {
type: Object,
default: () => ({})
},
disabled: {
type: Boolean,
default: false
},
customColor: {
type: String,
default: ''
},
fileSizeLimit: {
type: Number,
default: 2
},
fileTypeLimit: {
type: Array,
default: () => ['jpg', 'jpeg', 'png', 'gif']
}
},
data() {
return {
fileList: [],
uploadPercentage: 0,
status: 'warning'
}
},
methods: {
beforeUpload(file) {
const isLtSize = file.size / 1024 / 1024 < this.fileSizeLimit
const fileTypeArr = file.name.split('.')
const fileType = fileTypeArr[fileTypeArr.length - 1].toLowerCase()
const isFileType = this.fileTypeLimit.includes(fileType)
if (!isLtSize) {
this.$message.error(`上传图片不能超过 ${this.fileSizeLimit}MB!`)
return false
}
if (!isFileType) {
this.$message.error('上传图片格式必须是' + this.fileTypeLimit.join('、'))
return false
}
return true
},
handleSuccess(response, file, fileList) {
if (response.code !== '0') {
this.$message.error('上传失败')
return
}
const { data } = response
if (data && data.length > 0) {
data.forEach(item => {
this.fileList.push({
url: item.url,
name: item.name
})
})
this.status = 'success'
}
},
handleProgress(event, file, fileList) {
this.uploadPercentage = Math.floor(event.percent)
},
handleDelete(index) {
this.fileList.splice(index, 1)
this.$refs.upload.clearFiles()
this.uploadPercentage = 0
this.status = 'warning'
}
},
watch: {
fileList: {
handler(val) {
this.$emit('update:fileList', val)
},
deep: true
}
}
}
</script>
通过上面的示例说明,读者可以了解到我们如何封装一个上传图片组件,以及如何实现多图上传和自定义上传按钮。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:vue封装组件之上传图片组件 - Python技术站