自定义组件:Upload封装
最近项目是用iView组件库进行开发,里面的Upload上传组件用的频繁,所以我稍微进行了一下封装并配合表单以及v-model使用,简化代码方便使用。下面捋一捋过程和思路。
一、引入Upload组件:
官网:https://www.iviewui.com/components/upload

把这段代码连同样式先复制到自己的代码里。
二、在props里面写好父组件要使用的数据和类型:
props: {
// 上传路径
action: {
type: String,
default: "/yhsboot/upload/file"
},
// 请求头(可以用于鉴权)
headers: {
type: Object,
},
// 默认列表
defaultList: {
type: Array
},
// 格式
format: {
type: Array,
default: function () {
return ['jpg','jpeg','png']
}
},
// 大小
size: {
type: Number,
default: 2
},
// 数量
limit: {
type: Number,
default: 5
},
width: {
type: String,
default: '60px'
},
height: {
type: String,
default: '60px'
},
}
若还有什么要更改的数据可以自行设置,props改了,Upload也要改
<Upload
ref="upload"
:show-upload-list="false"
:default-file-list="defaultList"
:on-success="handleSuccess"
:format="format"
:max-size="size*1024"
:on-format-error="handleFormatError"
:on-exceeded-size="handleMaxSize"
:before-upload="handleBeforeUpload"
multiple
:headers="headers"
:action="action"
type="drag"
style="display: inline-block;">
...
</Upload>
数据变了,记得把methods和data里面的数据也相应改一下,避免报错。
使用一下就是这样,image-upload就是自己定义的名字:
<image-upload
:defaultList = "defaultList"
:headers="upHeaders"
:limit="3"
>
</image-upload>
这个时候使用组件看到的效果是这样的:

三、关于图片尺寸的设置:
可以看到我前面props里面设了width和height的值,要设置它们的值,那么样式不要写死,然后在需要设置宽高的地方,更改代码如下:
:style="{width: width, height: height, lineHeight: height}"
至此基础部分已经完成。
四、与v-model绑定:
上传组件95%的情况都是搭配表单使用,所以如果不能轻松配合表单,那么我们自定义封装的组件就没有意义了。首先在自定义组件里面加上代码:
model: [{
// 注意event的名字就叫input
prop: 'uploadList',
event: 'input'
}]
这里的uploadList就是图片数据,也是你v-model绑定后拿到的数据。
然后写一个初始化方法:
// 初始化
init() {
this.$emit('input',this.hanldeList(this.uploadList))
}
hanldeList方法就是处理图片的数据格式,可以返回数组,可以返回对象,可以返回字符串,可以根据情况灵活设定。由于平时用的最多的是数组,所以我的写法如下:
hanldeList(arr) {
// 当限制图片数量为单张时默认传字符串,为多张时传数组
if(this.limit === 1){
return arr[0].url
}else{
let new_arr = [];
arr.map((val,ind)=>{
new_arr.push(val.url)
})
return new_arr
}
}
注意我这里当图片限制为一张时(比如头像上传),返回字符串,其余情况返回数组。
最后一步不要忘记,在mounted生命周期里调用init方法,不然默认列表在v-model里面拿不到数据。
mounted () {
this.uploadList = this.$refs.upload.fileList;
this.init();
}
接下来使用看看。
五、搭配Form表单使用:
<Form :model="formCustom">
<FormItem label="图片:" prop="uoloadList">
<image-upload
:defaultList = "defaultList"
:headers="upHeaders"
v-model="formCustom.uoloadList">
</image-upload>
</FormItem>
<FormItem>
<Button type="primary" @click="handleSubmit('formCustom')">提交</Button>
</FormItem>
</Form>
handleSubmit (name) {
console.log("表单数据111",this.formCustom)
},

控制台打印如下:

可以看到已经达成我们要的效果了。
六、自定义插槽:
然而我还觉得不够,毕竟设计图中上传图标可不一定长这个样,所以如果要更改图标,那么就要利用起插槽了。然后我在Upload里面加入一段代码:
<slot name="upload">
<div :style="{width: width, height: height, lineHeight: height}">
<slot name="icon">
<Icon type="ios-camera" size="20"></Icon>
</slot>
</div>
</slot>
经过我思考,我觉得改的最多的就两个地方,一个是图标,插槽名叫icon,使用如下:
<image-upload
:defaultList = "defaultList"
:headers="upHeaders"
>
<template slot="icon">
<Icon type="md-cloud-upload" size="24" color="#57a3f3" />
</template>
</image-upload>

甚至还可以更改整个上传框的样式,插槽名为upload:
<image-upload
:headers="upHeaders"
>
<template slot="upload">
<div style="width: 200px; height: 90px; lineHeight: 90px">
<p>
<Icon type="md-cloud-upload" size="24" color="#57a3f3" />
请上传清晰的照片
</p>
</div>
</template>
</image-upload>

至此算是大功告成。
七、总结:
这次自定义组件算是磕磕碰碰完成了,自己抽时间一点点的测试,完成了也特别有成就感。个人认为自定义组件封装能综合考察对vue.js的掌握,难怪不少公司面试时也喜欢问有没有自己封装过组件。也希望自己不断学习,不断进步,特写此博客与君共勉。