Jeecg-boot 开发挖坑日记02 用户头像上传 / Vue-AntD上传组件

项目正式开始,第一个功能模块的用户信息编辑就开始卡壳,特别是头像上传组件。

  • 弹出框 a-mdal 的表单值怎么获取到的
  • ant-design-vue 上传组件的头像上传

使用 ant-design-vue 上传组件的头像上传。

在 Jeecg-boot 中头像上传是 antD 的上传组件 listType="picture-card"
在教程里是直接使用 upload 组件的 defaultFileList API,
但他们 DEMO 是 listType="text",或 listType="picture-card" 但绑定的是 fileList
并不是 defaultFileList,就和 ant-design-vue 的文档是一摸一样的照着读了一遍,

然后我直接复制的官方用户头像 DEMO,就出现了问题。

AntD 官方 DEMO

点击上传用户头像,并使用 beforeUpload 限制用户上传的图片格式和大小。beforeUpload 的返回值可以是一个 Promise 以支持异步处理,如服务端校验等

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
<template>
<a-upload
name="avatar"
listType="picture-card"
class="avatar-uploader"
:showUploadList="false"
action="https://www.mocky.io/v2/5cc8019d300000980a055e76"
:beforeUpload="beforeUpload"
@change="handleChange"
>
<img v-if="imageUrl" :src="imageUrl" alt="avatar" />
<div v-else>
<a-icon :type="loading ? 'loading' : 'plus'" />
<div class="ant-upload-text">Upload</div>
</div>
</a-upload>
</template>
<script>
function getBase64(img, callback) {
const reader = new FileReader();
reader.addEventListener("load", () => callback(reader.result));
reader.readAsDataURL(img);
}
export default {
data() {
return {
loading: false,
imageUrl: ""
};
},
methods: {
handleChange(info) {
if (info.file.status === "uploading") {
this.loading = true;
return;
}
if (info.file.status === "done") {
// Get this url from response in real world.
getBase64(info.file.originFileObj, imageUrl => {
this.imageUrl = imageUrl;
this.loading = false;
});
}
},
beforeUpload(file) {
const isJPG = file.type === "image/jpeg";
if (!isJPG) {
this.$message.error("You can only upload JPG file!");
}
const isLt2M = file.size / 1024 / 1024 < 2;
if (!isLt2M) {
this.$message.error("Image must smaller than 2MB!");
}
return isJPG && isLt2M;
}
}
};
</script>
<style>
// css style...
</style>

第一天的时候,我直接复制的 用户头像 DEMO,然后直接使用了 defaultFileList 设置默认头像但是没效果,依然是空白。

找啊找啊找,发现 DEMO 上设置了 :showUploadList="false",删之…🙄 还是不行,继续查问题。

发现 defaultFileList 是不能异步设置的,要在组件初始化完成之前就设置好,或者使用 fileList 来设置默认头像 🙃,

emmm….怎么还有一个空白头像,原来还有一个 img 标签,删之。

现在的 upload 组件是这样的:

1
2
3
4
5
6
7
8
9
10
11
<a-upload
action="https://www.mocky.io/v2/5cc8019d300000980a055e76"
listType="picture-card"
:defaultFileList="fileList"
@change="handleChange"
>
<div v-if="fileList.length < 1">
<a-icon :type="loading ? 'loading' : 'plus'" />
<div class="ant-upload-text">Upload</div>
</div>
</a-upload>

好,现在基本显示没问题了,但是先要删除原先的头像再上传

等等..删除了头像怎么没出现上传头像按钮?handleChange 事件要修改成:

1
2
3
handleChange({ fileList }) {
this.fileList = fileList;
},

完事,基本完成。
但是…

需求:点击头像就能修改,而不是先要删除原先的头像再上传

所以结合两个官方 DEMO,最后修改如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
<template>
// 上下文...
<a-upload
listType="picture-card"
class="avatar-uploader"
:showUploadList="false"
:action="uploadURL"
:beforeUpload="beforeUpload"
@change="handleChange"
>
<img v-if="imageUrl" :src="imageUrl" alt="avatar" style="width:100%;" />
<div v-else>
<a-icon :type="loading ? 'loading' : 'plus'" />
<div class="ant-upload-text">Upload</div>
</div>
</a-upload>
// 上下文...
</template>
<script>
export default {
data() {
return(){
url:{
upload: '/project/upload'
},

imageUrl: '',
loading: false
}
},
computed: {
uploadURL() {
return `${window._CONFIG['domianURL']}${this.url.upload}`
}
},
methods:{
handleChange(info) {
if (info.file.status === 'uploading') {
this.loading = true
return
}
if (info.file.status === 'done') {
getBase64(info.file.originFileObj, imageUrl => {
this.imageUrl = imageUrl
this.loading = false
})
// 这里可以放上传成功后台返回的图片url的表单赋值,使用 form.setFieldsValue 给表单赋值
}
},
beforeUpload(file) {
const isJPG = file.type === 'image/jpeg'
if (!isJPG) {
this.$message.error('You can only upload JPG file!')
}
const isLt2M = file.size / 1024 / 1024 < 2
if (!isLt2M) {
this.$message.error('Image must smaller than 2MB!')
}
return isJPG && isLt2M
}
// 初始图片赋值等方法
...
}
</script>
<style>
// css style...
</style>

弹出框的表单值是怎么设置的?

edit() 方法中传入了当前对象 record

AntD 封装了表单域 <Form.Item /> ,需要使用 Form.create 来创建表单实例,
而且设置表单的值要用 form.setFieldsValue (有些时候需要确保子组件完成渲染 $nextTick() 后才执行赋值操作)

且使用 pick()[1] 函数从指定的对象中挑选出需要的任意 key 属性。

特殊控件(select,radio,checkbox)需要使用 v-decorator 来绑定数据 [2]

尾声

  • 1,官方 DEMO 的代码差异比较大,特别是 handleChange 部分,需要细看。
  • 2,对后台返回的数据有要求。
  • 3,表单修改需要使用 setFieldsValue 来动态设置其他控件的值。

[ 注 1 ]: pick() 的坑待填,用的 lodash.pick 函数

[ 注 2 ]: 这里的 v-decorator 挖坑,看后边什么时候填上