不知道大家使用 Ant Design Vue 的时候有没有感觉不太顺手的地方,有些组件属性总是写的很隐蔽,有点磕磕绊绊的感觉。本篇博客记录一下我这一段儿时间使用 Ant Design Vue 踩过的一些坑,本文会持续更新~
Select
滚动定位问题
正常情况下,Select
的下拉框内容可以正确定位在 Select
下方,但是在微前端中,Select
的下拉框内容可能会出现定位问题,不会随着页面滚动而滚动,而是定位在了页面的某个位置。
这是因为 Select
的下拉框内容默认渲染定位到 body 上;在微前端中,我们知道子应用是被嵌套在主应用的某个容器 DIV 里面,而不是整个页面的 body 上,这就导致了 Select
的下拉框内容在页面出现滚动条的时候不能正确定位。
getPopupContainer
属性可以解决这个问题,
参数 | 说明 | 类型 | 默认值 |
---|---|---|---|
getPopupContainer | 菜单渲染父节点。默认渲染到 body 上,如果你遇到菜单滚动定位问题,试试修改为滚动的区域,并相对其定位。 | Function(triggerNode) | () => document.body |
<a-select
:getPopupContainer="
triggerNode => {
return triggerNode.parentNode || document.body;
}
"
>
</a-select>
其他组件类似,如 DatePicker 日期选择框有 getCalendarContainer
属性;Dropdown 下拉菜单有 getPopupContainer
属性;等等。
修改组件样式
Table 组件
<Table :dataSource="dataSource" :columns="columns" class="example-table-wrap"/>
<Table :dataSource="dataSource" :columns="columns"/>
如果想修改页面中第一个表格 class 是 example-table-wrap
字体大小,页面其他表格字体不变,怎么实现呢?
两种方式,一种是在 scoped
中添加样式,另一种是全局的添加。
方式一:对于 scoped
的代码片段,需要使用深度作用选择器 >>>
。
class 为 example-table-wrap
的 DIV 打上了 data-v-7ba5bd90
标志,所以需要使用深度作用选择器 >>>
选中子组件的样式进行修改:
<style scoped>
.example-table-wrap >>> .ant-table{
font-size: 12px;
}
</style>
转义后:
<style>
.example-table-wrap[data-v-7ba5bd90] .ant-table {
font-size: 12px
}
</style>
方式二:全局修改。
<style>
.example-table-wrap .ant-table{
font-size: 12px;
}
</style>
也可以实现,推荐第一种写法,相比较第二种写法,第一种更不容易引起全局环境变量污染。
Modal 对话框
如果认为 Modal 对话框样式的修改跟 Table 组件修改方式一样可以使用 scoped
+ >>>
,那就大错特错了。同样的,我们给 Modal 对话框一个 class 类 example-modal
,会发现默认 Modal 对话框并没有打上 data-v-7ba5bd90
标志:
这样的话,我们就不能用第一种方式 scoped
+ >>>
去修改它的样式,只能用全局样式修改了:
<style>
.example-modal .ant-modal-body{
padding: 12px;
}
如果仔细看 Modal 的 API 的话就可以看到,还可以通过 bodyStyle
属性去修改 Modal 的样式:
参数 | 说明 | 类型 | 默认值 |
---|---|---|---|
bodyStyle | Modal body 样式 | object | {} |
<Modal
:bodyStyle="{color: 'red', padding: '12px'}"
>
</Modal>
Tooltip 文字提示
如果我们想修改 Tooltip 的样式的话,可以使用 overlayClassName
和 overlayStyle
参数 | 说明 | 类型 | 默认值 |
---|---|---|---|
overlayClassName | 卡片类名 | string | 无 |
overlayStyle | 卡片样式 | object | 无 |
但是注意是全局变量使用方式:
<template>
<Tooltip color="white" class="example-tooltip" overlayClassName="example-overlay">
<template #title>prompt text</template>
Tooltip will show when mouse enter.
</Tooltip>
</template>
<style>
.example-overlay .ant-tooltip-inner{
color: black;
padding: 12px;
}
</style>
修改 Table 列的颜色
可以使用 rowClassName
修改表格行的样式,修改表格列的样式 API 文档并没有给出。用过 ant design React 版本的同学知道 Column
属性有一个 className
可以设置列样式类名。通过查看 Ant Design Vue 的源码发现也有这个属性可以使用,疑惑的点是为什么官方 API 不写全一点呢?还要用户去推测?😤
<script setup>
const columns = [
{
title: '姓名',
dataIndex: 'name',
key: 'name',
className: 'example-column-class'
},
]
</script>
修改表头样式:
<style>
th.example-column-class{
color: red;
}
</style>
修改列的样式:
<style>
tr.example-column-class{
color: red;
}
</style>
select 组件 placeholder 属性不起作用
这也是比较常见的一个使用问题,刚使用 Ant Design Vue 组件常见的一个问题。一般因为 select 绑定的参数(selectParam
),初始值为空字符串(''
)导致的,设置为 undefined
即可解决该问题
<Select
v-model:value="selectParam"
placeholder="请选择"
:options="options3">
</Select>
<script setup>
const selectParam = ref('')
</script>
<script setup>
const selectParam = ref()
</script>
表单验证的问题
对于 Ant Design Vue 3 版本之前,如果表单验证的 rules
规则里对于 DatePicker 日期选择组件的 type
没有定义会出现即使用户已经选中了日期,仍然校验不通过的问题。
const rules = {
date1: [{ required: true, message: 'Please pick a date', trigger: 'change', type: 'object' }]
}
默认 type 是 string
类型,如果类型不匹配,对于 Ant Design Vue 3 版本之前是会报错的。需要加上对应的类型 type: 'object'
才可以解决。
如果限制可以取多种类型怎么处理呢?
目前 async-validator 还没有可以限制多种类型的处理,需要我们自己写自定义校验规则实现,或者使用 type: 'any'
来实现。
Table 添加 rowKey
方式一:
<Table
:columns="columns"
:data-source="tableData"
:rowKey='record=>record.id'/> // id为 tableData 中的一个属性
方式二:
<Table
:columns="columns"
:data-source="tableData"
:rowKey="(record,index)=>{return index}"> //record 为每一条数据, index 索引
方式三:
<Table
:columns="columns"
:data-source="tableData"
rowKey="id"> // id为 tableData 中的一个属性 !!! 这里的rowKey不需要冒号
# antdesign-vue的table三种加rowkey的方式
DatePicker 绑定 string 类型
参数 | 说明 | 类型 | 默认值 |
---|---|---|---|
valueFormat | 可选,绑定值的格式,对 value、defaultValue、defaultPickerValue 起作用。不指定则绑定值为 moment 对象 | string,具体格式 | - |
<a-date-picker
v-model:value="expireDate"
format='YYYY-MM-DD'
value-format='YYYY-MM-DD'
/>
这样我们绑定的 expireDate
变量为 string
类型,直接用于后端数据发送。妈妈再也不用担心我 moment
类型和 string
类型转换来转换去了
关联的表单校验
如上图,两个时间选择框不仅不要校验非空,而且还需要校验彼此是否满足条件。可以使用自定义 validator 来实现,当 travelStartTime
和 travelEndTime
变化的时候调用 formRef.value.validateFields('travelStartTime');
和 formRef.value.validateFields('travelEndTime');
触发校验。
const checkStartTime = async (rule: RuleObject, value: string) => {
if (!value) {
return Promise.reject('请选择开始日期');
} else {
if(dayjs(formState.travelEndTime).isBefore(value)){
return Promise.reject('开始日期不应晚于结束日期');
}
}
return Promise.resolve();
};
const checkEndTime = async (rule: RuleObject, value: string) => {
if (!value) {
return Promise.reject('请选择开始日期');
} else {
if(dayjs(formState.travelStartTime).isAfter(value)){
return Promise.reject('结束日期不应早于开始日期');
}
}
return Promise.resolve();
};
const rules = {
travelEndTime: [
{
required: true, type: 'string', validator: checkEndTime
},
],
travelStartTime: [
{
required: true, type: 'string', validator: checkStartTime
},
],
}
watch([() => formState.travelStartTime, () => formState.travelEndTime], ([newStart, newEnd]) => {
if (newEnd) {
formRef.value.validateFields('travelEndTime')
}
if (newStart) {
formRef.value.validateFields('travelStartTime')
}
})
内置 TS 的类型
import { ColumnProps, TableState } from 'ant-design-vue/es/table/interface'