Ant Design Vue遇到的问题和解决记录

简介

开箱即用的高质量 Vue 组件。

安装

使用 npm 或 yarn 安装 #

我们推荐使用 npm 或 yarn 的方式进行开发,不仅可在开发环境轻松调试,也可放心地在生产环境打包部署使用,享受整个生态圈和工具链带来的诸多好处。

1
2
$ npm install ant-design-vue --save
$ yarn add ant-design-vue

如果你的网络环境不佳,推荐使用 cnpm

树形图

折叠展开-控制展开指定节点

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
<a-tree
v-model="checkedKeys"
checkable
draggable
:blockNode="true"
:tree-data="treeData"
show-icon
:expandedKeys="expandedKeys"
@select="onSelect"
@expand="onExpand"
@dragenter="onDragEnter"
@drop="onDrop"
@check="onCheck"
>

data() {
return {
// 控制展开节点
expandedKeys: [],
}
}

expandedKeys 折叠展开的节点
onExpand 点击折叠展开触发的方法


// 折叠展开时
onExpand(val) {
console.log('Trigger Expand', val)
this.expandedKeys = val
},

渲染数据后-默认展开无效

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
分析原因:antdesignvue的前端是一次性渲染的,所以defaultExpandedRowKeys等只在渲染时有效。
解决方法:添加判断v-if你的DataSource长度,如果为0则不渲染。
动态解决方法:在DataSource赋值的时候,使用splice将其长度变为0

this.DataSource.splice(0)
1
<a-row class="tree-box">
<a-col>
<a-tree
v-if="DataSource.length>0"
v-model="checkedKeys"
checkable
:auto-expand-parent="autoExpandParent"
defaultExpandAll
:tree-data="DataSource"
/>
</a-col>
</a-row>
————————————————
版权声明:本文为CSDN博主「三个人工作室」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/wwppp987/article/details/113737659

dwy案例 v-if="treeData.length > 0" 就可以了
<a-tree
v-if="treeData.length > 0"
:default-expanded-keys="showkeys"
:show-line="true"
:tree-data="treeData"
:replaceFields="replaceFields"
:selected-keys="selectedKeys"
@select="onSelect"
>
</a-tree>

表单

表单验证规则

prop=”poolName 和 v-model=”formData.poolName” 对应 必须要有v-model

1
2
3
4
5
6
7
8
9
10
<a-form-model
ref="ruleForm"
:rules="rules"
:model="formData"
:label-col="formItemLayout.labelCol"
:wrapper-col="formItemLayout.wrapperCol">
<a-form-model-item label="人才库名称" prop="poolName">
<a-input v-model="formData.poolName"/>
</a-form-model-item>
</a-form-model>

rules 代码参考

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
  rules: {
poolName: [{
validator: (rule, value, callback) => {
console.log('rule',rule);
console.log('value',value);
console.log('callback',callback);
if (value) {

if(value.length > 10){
callback(new Error('限制10个字符以内'));
}else{
callback();
}
} else {
callback(new Error('请填写选项名称'));
}
}, trigger: ['change', 'blur']
}],
poolColor: [{
validator: (rule, value, callback) => {
if (value) {
callback();
} else {
callback(new Error('请选择颜色'));
}
}, trigger: ['change', 'blur']
}],
//或者
severName: [
{ required: true, message: '请输入目标服务器', trigger: 'blur', whitespace: true }
]
}

InputNumber 数字输入框 只能输入数字

1
:formatter="value => `${value}`.replace(/\D/g, '')"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<a-form-model-item label="排序">
<a-input-number
:formatter="value => `${value}`.replace(/\D/g, '')"
v-model="formData.roleSort"
:min="1"
:precision="0"
style="
width: 100%;
height: 48px;
background-color: #f7f9fb !important;
border-radius: 4px;
border: none;
"
/>
</a-form-model-item>

验证规则参考

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
let rulesItem = {
validator: (rule, value, callback) => {
console.log('value',value);
console.log('value.length',value.length);
if(that.title == '能力素质'){
if (value <= 100) {
callback();
} else {
callback(new Error(`${item.dictLabel}不能大于100`));
}
}
if (Array.isArray(value)) {
if (value.length) {
callback();
} else {
callback(new Error(`请完善${item.dictLabel}`));
}
} else {
if (value) {
callback();
} else {
callback(new Error(`请完善${item.dictLabel}`));
}
}
},
};
if (item.cssClass == 1) {
rulesItem.trigger = "change";
} else if (item.cssClass == 2) {
rulesItem.trigger = "change";
} else if (item.cssClass == 3) {
rulesItem.trigger = "blur";
} else if (item.cssClass == 4) {
rulesItem.trigger = "change";
}
rules[`formData${index}`] = rulesItem;
});
this.form = form;
console.log(this.form);
this.rules = rules;
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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
rules: {
nickName: [
{
required: true,
message: "请填写用户姓名",
trigger: ["change", "blur"],
},
{
validator: function (rule, value, callback) {
if (value.length < 10) {
callback();
} else {
callback("最多10个字符");
}
},
trigger: ["change", "blur"],
},
],
deptId: [
{
required: true,
message: "请选择部门",
trigger: ["change", "blur"],
},
],
postId: [
{
required: true,
message: "请选择岗位",
trigger: ["change", "blur"],
},
],
// MBdeptId: [
// {
// required: true,
// message: "请选择目标部门",
// trigger: ["change", "blur"],
// },
// ],
MBpostId: [
{
required: true,
message: "请选择目标岗位",
trigger: ["change", "blur"],
},
],
email: [
// {
// required: true,
// message: "请填写电子邮箱",
// trigger: ["change", "blur"],
// },
{
validator: function (rule, value, callback) {
if (value) {
var emailRegExp =
/^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/;
if (emailRegExp.test(value)) {
callback();
} else {
callback("电子邮箱格式错误");
}
}else{
callback();
}
},
trigger: ["change", "blur"],
},
],
phonenumber: [
{
required: true,
message: "请填写手机号码",
trigger: ["change", "blur"],
},
{
validator: function (rule, value, callback) {
const phonenumberREP = /^1[0-9]{10}$/;
if (phonenumberREP.test(value)) {
callback();
} else {
callback("手机号码格式错误");
}
},
trigger: ["change", "blur"],
},
],
roleId: [
{
required: true,
message: "请选择角色",
trigger: ["change", "blur"],
},
],
perNo: [
{
required: true,
message: "请填员工编号",
trigger: ["change", "blur"],
},
],
userLevel: [
{
required: true,
message: "请选择用户等级",
trigger: ["change", "blur"],
},
],
userWorkType: [
{
required: true,
message: "请选择用户等级",
trigger: ["change", "blur"],
},
],
},

表格多选及验证

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
<a-form-model ref="formModel" id="components-form" :model="form" :rules="rules">


<a-form-model-item label="报表内容" prop="BBcontent" ref="BBcontent" :label-col="{ span: 3 }"
:wrapper-col="{ span: 20, offset: 1 }">
<div class="bbnr">
<a-checkbox-group :options="checkboxData" v-model="form.BBcontent" @change="BBonChange" />
</div>
</a-form-model-item>

</a-form-model>


form: {
BBcontent: [], // 报表内容
},

checkboxData: [
{ value: '1', label: '服务器运行情况' },
{ value: '2', label: 'GPU使用情况' },
{ value: '分布式存储使用情况', label: '分布式存储使用情况' },
{ value: 'IB网络使用情况', label: 'IB网络使用情况' },
{ value: 'RoCE网络使用情况', label: 'RoCE网络使用情况' },
{ value: '交换机使用情况', label: '交换机使用情况' },
{ value: '防火墙使用情况', label: '防火墙使用情况' },
{ value: '堡垒机使用情况', label: '堡垒机使用情况' },
{ value: '报警事件情况', label: '报警事件情况' },
],

// 验证规则
rules: {
// 报表内容
BBcontent: [{
type: 'array',
required: true,
message: '请选择报表内容',
trigger: 'change',
whitespace: true
}],
}


methods: {
BBonChange(val) {
console.log('val', val);
this.form.BBcontent = val
},
}


验证事件触发后没有触发验证规则问题

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
正确格式
<a-row class="form_li" type="flex" justify="center">
<a-col :xs="formW" :sm="formW" :md="formW" :lg="formW" :xl="formW">
<a-form-model-item label="设备类型" prop="equipmentType">
<a-select v-model="form.equipmentType" placeholder="请选择类型" allowClear @change="equipmentTypechange">
<a-select-option value="shanghai">
Zone one
</a-select-option>
<a-select-option value="beijing">
Zone two
</a-select-option>
</a-select>
</a-form-model-item>
</a-col>
</a-row>


错误格式 a-form-model-item里面多包了一层div 导致 验证事件触发后没有触发验证规则问题

<a-row class="form_li" type="flex" justify="center">
<a-col :xs="formW" :sm="formW" :md="formW" :lg="formW" :xl="formW">
<a-form-model-item label="设备类型" prop="equipmentType">
<div>
<a-select v-model="form.equipmentType" placeholder="请选择类型" allowClear @change="equipmentTypechange">
<a-select-option value="shanghai">
Zone one
</a-select-option>
<a-select-option value="beijing">
Zone two
</a-select-option>
</a-select>
</div>
</a-form-model-item>
</a-col>
</a-row>



// 验证规则
rules: {
// 设备类型
equipmentType: [{
required: true,
message: '请选择设备类型',
trigger: 'change',
// whitespace: true
}],

多表单验证

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
onSubmit() {
this.$refs.formModel.validate(valid1 => {
console.log('表单1验证',valid1);
if (valid1) {

// 发送通知
if(this.form.ifInform == 2){
console.log('进来');
this.$refs.formModel2.validate(valid2 => {
console.log('表单2验证',valid2);
})
}
} else {
// this.loading = false
console.log('error submit!!')
return false
}
})
},

下拉选择样式,文字过长时省略号

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
<a-form-item label="GPU类型:" :label-col="{ span: 7 }" :wrapperCol="{ span: 14 }">
<a-select :placeholder="$t('pSelectText')" v-model="queryParam.gpuType" @change="changetype">
<a-select-option v-for="item in severstypeOptions" :value="item.id">{{
item.value }}</a-select-option>
</a-select>
</a-form-item>


踩坑有bug 里面内容过长时 在不同尺寸下适配会有问题

用的下面的解决方案

<a-form-item label="服务器所属分组:" class="selectbox1" >
<a-select :placeholder="$t('pSelectText')" v-model="queryParam.groupId" @change="changeGroup">
<a-select-option v-for="item in groupOptions" :value="item.aegId">{{ item.groupName
}}</a-select-option>
</a-select>
</a-form-item>

单独设置左侧label 样式 和右侧盒子宽度
<style lang="less">
// 调整查询样式 服务器所属分组
.selectbox1 .ant-form-item-label {
width: 112px;

}

.selectbox1 .ant-form-item-control-wrapper {
width: calc(100% - 112px);

}
</style>

深度样式修改::v-deep

1
::v-deep .ant-tabs-nav-scroll {

字体

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
阿里字体 包下载

main.js

import Vue from 'vue'
import { Icon } from 'ant-design-vue'
import iconFont from './assets/icons/iconfont.js'
import iconFontCss from './assets/icons/iconfont.css'


Vue.use(iconFontCss)


const myicon = Icon.createFromIconfontCN({
scriptUrl: iconFont
})
//引用
Vue.component('icon-font', myicon)


参考
https://blog.csdn.net/sinat_40470998/article/details/110531033


树形表格折叠不管用bug

核心 expandedRowsChange 官方文档没有

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
68
69
70
71
72
<a-table :columns="columns" :data-source="data" :row-selection="rowSelection" @expandedRowsChange="jkl"
:expanded-row-keys.sync="expandedRowKeys" />

核心 expandedRowsChange 官方文档没有

data() {
return {
expandedRowKeys: [],





jkl(e) {
console.log('this.expandedRowKeys',this.expandedRowKeys);
console.log('e',e);
// this.expandedRowKeys = [...this.expandedRowKeys, ...e]
this.expandedRowKeys = e
},

:row-selection="rowSelection 控制多选的 可以不要



数据
data: [
{
key: 1,
name: 'John Brown sr.',
age: 60,
address: 'New York No. 1 Lake Park',
children: [
{
key: 11,
name: 'John Brown',
age: 42,
address: 'New York No. 2 Lake Park',
},
{
key: 12,
name: 'John Brown jr.',
age: 30,
address: 'New York No. 3 Lake Park',
},
],
},
{
key: 2,
name: 'Joe Black',
age: 32,
address: 'Sidney No. 1 Lake Park',
},
],
columns: [
{
title: 'Name',
dataIndex: 'name',
key: 'name',
},
{
title: 'Age',
dataIndex: 'age',
key: 'age',
width: '12%',
},
{
title: 'Address',
dataIndex: 'address',
width: '30%',
key: 'address',
},
],

树形表格折叠按钮自定义

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
68
69
70
71
72
73
74
75
76
77
78
79
位置
<a-table
:columns="columns"
:data-source="data"
class="components-table-demo-nested"
:expandIconColumnIndex="2"
:expandIcon="expandIcon"
:expandIconAsCell="false"
></a-table>

在原本代码的基础上,在<a-table>中添加

:expandIconColumnIndex="3"

:expandIconAsCell="false"

想把展开按钮放在第几列,就给expandIconColumnIndex设置多少值(第1列为0,以此类推)

expandIconAsCell这个属性也要加,不加按钮换位不起作用

设置完后,展开按钮变为下图位置。


dwy测试不加:expandIconAsCell="false" 没发现问题

自定义按钮 可用阿里图表
:expandIcon="expandIcon"

methods: {
// 渲染打开子表格图标样式
expandIcon(props) {
console.log('props', props); //返回的是父表格中的所有数据内容
if (props.record.children) {
if (props.record.children.length > 0) {
//props.record的内容是表格单行的所有数据,可以在这里判定子表格是否有数据。
if (props.expanded) {
//props.expanded的值是true或false,代表子表格是否展开
//有数据展开时图标样式
return (
<a
onClick={(e) => {
console.log('e', e);
props.onExpand(props.record, e);
}}
>
网卡参数 <icon-font type="icon-xiangxia" style="font-size:18px;"></icon-font>

</a>
);
} else {
//有数据且未展开时图标样式
return (
<a
onClick={(e) => {
console.log('e', e);
props.onExpand(props.record, e);
}}
>
网卡参数 <icon-font type="icon-xiangshang" style="font-size:18px;"></icon-font>

</a>
);
}
} else {
//无数据时图标样式
return (
<span>
无数据

</span>
);
}
}

},


参考地址
https://blog.csdn.net/weixin_47437528/article/details/124870006

表格

表头样式自定义

方法1 插槽

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
columns:[
{
// title: 'ALL Errors',
ikey:'ALL Errors',
align: 'center',
ellipsis: true,
dataIndex: 'losslessAllErrors',
slots: { title: 'customTitle_ALLErrors' },
scopedSlots: {
customRender: 'customTitle_ALLErrors',
},
},

]

html
<div slot="customTitle_ALLErrors">
<div>ALL</div>
<div>Errors</div>
</div>



方法2 内部属性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
columns:[

{
title: 'GPU使用率',

align: 'center',
ellipsis: true,
dataIndex: 'gpuUsageRate',
title: () => {
return <a-tooltip placement="top" title="GPU使用率" >GPU使用率</a-tooltip>
},
},

]

如果有排序的话,自定义表头和排序有冲突,只能升序不能降序 slots和sorter冲突

表头自定义改用这个方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
{
title: () => {
return (
<div>
<div>ALL</div>
<div>Errors</div>
</div>
)
},
// title: 'ALL Errors',
ikey: 'ALL Errors',
align: 'center',
ellipsis: true,
dataIndex: 'losslessAllErrors',
orderFiled: 'lossless_all_errors',
// slots: { title: 'customTitle_ALLErrors' },
sorter: (a, b) => a.losslessAllErrors - b.losslessAllErrors,
scopedSlots: {
customRender: 'customTitle_ALLErrors',
},

},

排序 sorter
自定义排序 orderFiled 后台排序

方法3

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
 colnums: [
{
title: '长标题',
dataIndex: 'longTitle',
scopedSlots: {customRender: 'longTitle'},
align: 'center',
width: 120
customHeaderCell: () => {
return {
style: {
wordWrap: 'break-word',
wordBreak: 'break-all',
whiteSpace: 'normal',
minHeight: '50px',
width: '150px',
}
}
}
}
]

表体内容自定义

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
columns:[
{
// title: 'ALL Errors',
ikey:'ALL Errors',
align: 'center',
ellipsis: true,
dataIndex: 'losslessAllErrors',
slots: { title: 'customTitle_ALLErrors' },
scopedSlots: {
customRender: 'customTitle_ALLErrors',
},
},

]


<span slot="customTitle_ALLErrors" slot-scope="text, record"
:class="[distributedStorageId == record.distributedStorageId && 'selectedbar']">
{{ record.losslessAllErrors }}
</span>

连用案例

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
columns:[

{
// title: 'ALL Errors',
ikey:'ALL Errors',
align: 'center',
ellipsis: true,
dataIndex: 'losslessAllErrors',
slots: { title: 'customTitle_ALLErrors' },
scopedSlots: {
customRender: 'customTitle_ALLErrors',
},
},

]


html
<div slot="customTitle_ALLErrors">
<div>ALL</div>
<div>Errors</div>
</div>
<span slot="customTitle_ALLErrors" slot-scope="text, record"
:class="[distributedStorageId == record.distributedStorageId && 'selectedbar']">
{{ record.losslessAllErrors }}
</span>

修改样式无效

1
2
3
4
::v-deep .ant-popover-inner .ant-popover-title{
display: none !important;
}

加::v-deep

如果还无效 例如浮层组件

解决办法
在template模版里的代码写法
注意事项:在a-popover里加一个overlayClassName属性,其值可以自己定义卡片类名,定义卡片类型名之后就可以在style标签里进行修改卡片的样式了。
代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<a-popover  placement="bottom" trigger="click" overlayClassName="poperlay-table1">
<template slot="content">
<p>Content</p>
<p>Content</p>
</template>
<template slot="title">
<div>
123
</div>
</template>
<div>
{{ record.gpuUsageRate }}<span v-if="record.gpuUsageRate">%</span>
</div>
</a-popover>

在vue的组件里再加另一个style标签时不写scoped
注意事项:在自己所定义的卡片类名里,不加/deep/深度选择,才能进行样式的修改
代码如下

1
2
3
4
5
6
7
8
9
10
11
<style lang="less">
.poperlay-table1 .ant-popover-title{
display: none !important;
}
</style>


a-tooltip a-popove 都可用

a-form-item 用 class="selectbox1"
dropdown-class-name <a-form-item label="服务器所属分组:" class="selectbox1">

Tooltip如何只在内容溢出时显示,内容不溢出时不显示

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
https://blog.csdn.net/licongmingli/article/details/134711481
给Tooltip添加鼠标移入事件mouseenter,当内容没有溢出时阻止鼠标事件。
<a-tooltip placement="topLeft" :title="list" @mouseenter="showTooltip">
<div class="tag-container">
<span v-for="(item, index) in list" :key="index">
<a-tag style="margin-bottom:6px;">{{ item }}</a-tag>
</span>
</div>
</a-tooltip>


补充知识点:
clientHeight :元素像素实际高度。(内容有溢出时,理解为可视区域高度)
scollHeight:元素内容高度,包括溢出的不可见内容。(可视区域高度+被隐藏区域高度,当内容没有溢出时clientHeight ===> scollHeight )



// 控制Tooltip的显示与隐藏
showTooltip(e){
if(e.target.clientHeight === e.target.scollHeight){
// 阻止鼠标事件
e.target.style.pointerEvents = 'none'
}
}

样式:内容垂直排列,最多显示2行,所以在上面代码中通过比较高度判断内容是否溢出

<style>
.tag-container {
display: -webkit-box; /* 设置为弹性盒子*/
-webkit-box-orient: vertical; /* 垂直方向排列*/
-webkit-line-clamp: 2; /* 显示行数*/
overflow: hidden; /*隐藏溢出内容 */
padding: 0 8px;
}
</style>



Ant Design Vue遇到的问题和解决记录
http://www.dwyblog.cn/2024/02/18/Ant Design Vue遇到的问题和解决记录/
作者
幸福来敲门
发布于
2024年2月18日
许可协议