初期使用感受
element-UI 和 Ant Design Vue 的区别
我司现在和以前的后台主要 UI 框架是 element-ui
,在 Ant Design Vue
官宣之前就一直在关注,但是由于项目时间的不允许和 UI 框架稳定性的多方面考虑,一直都没机会尝试使用 antd
来搭建一个新的后台模版。
table
基本功能
自带分页、搜索、排序、自定义操作等功能
使用 slot 插入其他组件、展示数据
日常使用参数
<a-table
:columns="columns"
rowKey="id"
:dataSource="data"
:pagination="pagination"
@change="handleTableChange"
>
<template #cover_url="cover_url">
<my-image :src="cover_url"></my-image>
</template>
<template #has_pano_new="has_pano_new">
<span>{{has_pano_new}}slot插值</span>
</template>
<template #action="text, record">
<my-button
@click="changeStatus(record)"
:status="record.status"
></my-button>
<my-button @click="toEdit(record)" ghost type="edit"></my-button>
<my-button @click="remove(record)" ghost type="remove"></my-button>
</template>
</a-table>
data() {
return {
data: [
{
title: '操作',
dataIndex: 'action',
scopedSlots: { customRender: 'action' }
}
]
}
}
参数:
columns
: 表格每行的数据和定义表头dataSource:
表格全部数据,dataSource
和columns
里的数据值都需要指定key
值。对于dataSource
默认将每列数据的key
属性作为唯一的标识。rowKey
: 每行单独的key
,必须值,不可重复和不赋值,一般为id
>pagination
: 表格自带的分页,接受一个Obj
对象handleTableChange:
翻页触发的回调
slot 插值
#action="text, record"
相当于v-slot:action="text,record"
slot
中包含两个参数,第一个是当前列的值,参照cover_url
,record
代表的是当前行对应的值,相等于elment-ui
中scope.row
,都可以取得当前行的所有数据
排序和筛选
不需要指定具体的 onFilter
和 sorter
函数,而是在把筛选和排序的参数发到服务端来处理。
也可以通过 slot
来自定义筛选功能
[
{ title: 'Name',
dataIndex: 'name',
sorter: true,
scopedSlots: { customRender: 'name' }
},
{
title: 'Gender',
dataIndex: 'gender',
filters: [
{ text: 'Male', value: 'male' },
{ text: 'Female', value: 'female' },
],
}
]
handleTableChange (pagination, filters, sorter) {
// do something
}
form
最重要的表单数据填充、验证和提交
Ant-design-vue 的表单验证
<a-form-item v-bind="mapLayout" label="图片附件">
<hotel-upload
v-decorator="['attach', {initialValue: [],rules:[{validator: imageLengthValidate}]}]"
:limit="100"
:validate="validateImageSize"
>
</hotel-upload>
</a-form-item>
使用到的表单验证一般都会定义在 rules
中,但是也不能排除特出情况
例如在图片上传时需要判断图片的 size,主要氛围两种情况:
- 在上传到服务器之前,使用
new Image()
和URL.createObjectURL(file)
提前获得本地图片大小判断,不符合 size 就阻止上传; - 上传之后在提交时触发提交事件,主动触发表单的验证,使用图片的 URL 实例化本地图片在判断是否合规,决定是否可以提交
简单的自定义表单验证
// 表单中的input或者其他组件
// v-decorator ="['name', {initialValue: '', rules: [{required: true, message: 'some....'}, {validator: validator}]}]"
validator(file, value, callback) {
if(value === '....'){
// 验证没通过
callback('验证没通过')
} else {
callback()
}
// 无论验证是否通过,callback必须被调用
}
以此类推,我们可以为表单添加多个验证规则
rules:[{required: true, message: 'some....'}, {validator: imageLengthValidate}]
验证图片宽高大小的方式
- 上传至服务器之后的验证(通过表单验证的形式)
// 验证方法 utils.js
export function imageInfo(src) {
return new Promise((resolve, reject) => {
// 通过图片上传后的地址来验证
if (!/[jpeg|png|jpg|gif|svg|ico]/gi.test(src)) {
message.warning('请上传图片类型文件')
return
}
const img = new Image()
img.src = src
img.onload = function() {
const { width, height } = this
resolve({
height,
width
})
}
img.onerror = e => {
message.error('图片加载失败')
reject(e)
}
})
}
//表单中附加的验证方法
const imagesSize = async (file, value, callback) => {
let error = undefined
// 因为验证方法中使用是异步,所以不能使用map来对数组进行遍历,使用for循环可以很好的解决这这个问题
for (let i = 0; i < value.length; i++) {
// 循环遍历验证,但是问题是即使某张图验证失败了,不能准确定位到不合规格的图片
const { url } = value[i]
const { width, height } = await imageInfo(url)
if (width !== 1920 || height !== 1276) {
error = '尺寸限制:1920x1276'
break
}
}
callback(error)
}
- 上传之前的验证
utils.js
中定义一个公共验证的方法,在需要的时候通过 props 传到上传组件中
// utils.js
export function beforeImageInfo(file) {
// 无论失败还是成功都需要返回一个 `Promise`
return new Promise((resolve, reject) => {
if (!/^image\/[jpeg|png|jpg|gif|svg|ico]/gi.test(file.type)) {
message.warning('请上传图片类型文件')
return
}
const img = new Image()
img.src = URL.createObjectURL(file)
img.onload = function() {
const { width, height } = this
resolve({
height,
width
})
}
img.onerror = e => {
message.error('图片加载失败')
reject(e)
}
})
}
- 如何在封装的组件中使用验证,拦截一切我们不需要的内容
// 封装的组件中使用验证
async beforeUpload(file) {
if (file.size / 1000 > this.size) {
const message = '图片过大';
this.$message.warning(message);
return Promise.reject(message);
}
if (this.validate) {
await this.validate(file);
}
// 上传之前验证,不通过不上传
this.formData.token = await qnToken(this.tokenType);
return true;
}