桌面端列表类组件
桌面端提供表格、嵌套表格、表格单元格合并、冻结列、单选行、多选行、拖拽行、树形表格、树、列表和嵌套列表等列表形式,界面效果如下面几张图所示
- 表格支持多列头、总结栏、过滤条
- 嵌套表格
- 表格支持单元格合并
- 表格支持冻结列、列内容的超长省略
- 单选
- 多选
- 表格支持拖拽行(React 表格支持,Vue 表格不支持)
- 树形表格
- 树支持过滤
- 列表支持响应式
- 嵌套列表
表格组件
表格组件是列表页面中最常用的组件,和数据组件绑定后,显示数据组件中的数据,并实现双向数据绑定。
- 写入数据:用户录入,或通过代码赋值后,数据会写入数据组件
- 读取数据:表格组件实时显示数据组件中的数据,数据改变后,会立即显示新的数据
表格组件通过设置“绑定数据集”属性绑定到一个数据组件上,实现双向数据绑定。通过“添加列”设置表格中的显示列,如下图所示。
- 表格列中不放组件时,以文本的形式显示数据列中的内容。
- 表格中可以放任意组件,当组件需要设置“绑定数据列”时,必须设置为“表格当前行”的数据列
- 放表单类组件,表单类组件的“绑定数据列”绑定“表格当前行”的数据列,在表格中可以直接编辑数据
- 放图片组件,图片的“地址”属性绑定“表格当前行”的数据列,可以显示图片
- 放按钮组件,按钮的“文本”属性绑定“表格当前行”的数据列,可显示为一个带链接的按钮
- 在一个表格列中可以放多个组件
数据分页
数据组件有分页能力,表格组件也有分页能力
- 数据组件的分页是发送请求时携带分页信息,一次请求返回一页数据
- 表格组件的分页是对内部数据的分页显示
数据组件的分页和表格的分页搭配之后的效果,见下表
数据组件 | 表格组件 | 分页 | 说明 |
---|---|---|---|
分页 | 不分页 | 服务分页 | 一般情况都使用此方案,数据查询服务支持分页,且一页数据全部显示时使用 |
不分页 | 分页 | 前端分页 | 数据查询服务不支持分页,且数据需要分页显示时使用 |
分页 | 分页 | 大数据渲染分页 | 数据查询服务支持分页,但一次请求返回大量数据,这些数据需要分页显示时使用 |
服务分页
数据组件默认是分页加载的,即数据刷新后,只得到第一页的数据。表格组件显示数据组件中的数据,即显示出第一页的数据,在界面上通过“分页”组件加载第二页、第三页……的数据。分页组件和表格组件要绑定同一个数据集。
前端分页
表格可以显示数据组件中的全部数据,也可以对数据组件中的数据分页显示。例如数据组件中有100条数据,可以设置表格组件的“前端分页”属性为“是”,每页显示20条数据,分成5页显示。表格组件自己提供分页栏。
“前端分页”属性就是原生 Table 组件的 分页属性 pagination,支持设置每页条数、默认每页条数、是否显示 pageSize 切换器、是否显示快速跳转、显示数据总量
例如:设置默认每页条数为4、显示 pageSize 切换器,W 源码如下
pagination="{{{defaultPageSize:4,showSizeChanger:true}}}"
例如:设置每页条数为4,W 源码如下,设计界面如下图所示
pagination="{{{pageSize:4}}}"
例如:设置每页条数为4,显示 1 - 10 条/ 共 100 条
{{pageSize:4,showTotal:(total, range)=> `${range[0]} - ${range[1]} 条 / 共 ${total} 条`}}
运行效果,如下图所示
大数据量渲染分页
当数据组件一次返回的数据需要再次分页显示时,例如一次返回100条数据,表格中希望一页显示10条数据时,设置表格组件的“大数据量渲染分页”属性,不需要放分页组件,表格组件自己提供分页栏。
特别注意:这个“大数据量渲染分页”属性的值,必须能被数据组件的 limit 整除,避免出现表格的一页上面有数据组件两页的部分数据
- limit 默认为20,可以设置的值有1、2、4、5、10
- limit 设置为-1时,系统使用1000000计算
- “大数据量渲染分页”属性要设置为6,可以设置 limit 为一个能整除6的数,例如60
“大数据量渲染分页”属性设置,如下图所示
运行效果,如下图所示
滚动加载
表格组件设置“滚动分页”属性为“是”时,不需要使用“分页”组件,通过鼠标滚轮的滚动即可以加载下一页数据。和使用“分页”组件不同的是,使用“分页”组件时,表格中只显示新加载的数据。使用滚动分页时,表格中显示所有加载过的数据。
特别说明
- Vue 表格组件设置“滚动分页”属性为“是”时,还必须设置“纵向滚动高度”属性,才能实现滚动加载
排序/多列排序
表格组件支持本地数据排序、服务端数据排序、多列排序。
- 本地数据排序:仅对加载到数据组件中的数据进行排序
- 服务端数据排序:重新发送请求,按照排序设置,从数据库中重新查询数据
- 多列排序:设置列的“多列排序优先级”后,即使用多列排序。多列排序优先级中数字大的表示排序顺序在前,数字小的表示排序顺序在后。
单选行/多选行
表格组件使用“选中数据集”记住用户的选择,支持跨页。即用户在第一页选择了两行数据,切换到第二页,选择了三行数据,此时选中数据集中共有五行数据。当用户再次切换到第一页数据时,选择的两行数据还是选中状态。
表格组件“开启选择功能”后,会在表格左边第一列显示一个单选列或多选列。
在选择功能中,选择“单选”或“多选”,决定表格的选择方式,选择多选时,列头显示全选按钮。
准备一个选中数据集,和表格绑定的数据集一样,清空“自动模式”属性
在表格的“选中数据集”属性中绑定上一步添加的数据集,用户选择行后,选择的行数据会复制到这个选中数据集中
表格多选时的行数据,存入选中数据集,运行效果如下
特别说明
- 选中数据集为树形数据时,编辑该数据组件,取消勾选“树形数据”,作为普通数据使用
用代码控制选中状态
表格组件使用选中数据集存储选中行;也使用选中数据集中的数据,设置行的选中状态。因此通过修改选中数据集中的数据,可以实现选中和取消选中
案例一:选中或取消选中表格当前行
react 代码如下
onSelectCurrentRowBtnClick = (event) => {
let mainData = this.comp("mainData"); //获取表格组件绑定的数据集
let selectData = this.comp("selectData"); //获取表格组件绑定的选中数据集
let selectedRowKeys = selectData.getIDs(); //获取当前选中的数据的主键列表
let rowId = mainData.getCurrentRowID(); //获取数据组件当前行的主键值
if(selectedRowKeys.indexOf(rowId) > -1){ //已选中,取消选中
selectData.removeData(rowId); //取消选中
}else{
mainData.copyRows(rowId,"selectData"); //未选中,设置为选中
}
}
vue 代码如下
let $page = usePage();
let mainData= useData('mainData'); //获取表格组件绑定的数据集
let selectData = useData('selectData'); //获取表格组件绑定的选中数据集
onSelectCurrentRowBtnClick = (event) => {
let selectedRowKeys = selectData.getIDs(); //获取当前选中的数据的主键列表
let rowId = mainData.getCurrentRowID(); //获取数据组件当前行的主键值
if(selectedRowKeys.indexOf(rowId) > -1){ //已选中,取消选中
selectData.removeData(rowId); //取消选中
}else{
mainData.copyRows(rowId,"selectData"); //未选中,设置为选中
}
}
案例二:点击表格行时,实现选中或取消选中
react 代码如下
onMultiSelectTableRowClick = ({event,record,index}) => {
let mainData = this.comp("mainData"); //获取表格组件绑定的数据集
let selectData = this.comp("selectData"); //获取表格组件绑定的选中数据集
let selectedRowKeys = selectData.getIDs(); //获取当前选中的数据的主键列表
let idColumn = selectData.getIdColumn(); //获取选中数据集的主键列名
let rowId = record[idColumn]; //从表格当前行 record 中获取主键值
if(selectedRowKeys.indexOf(rowId) > -1){ //已选中,取消选中
selectData.removeData(rowId); //取消选中
}else{
mainData.copyRows(rowId,"selectData"); //未选中,设置为选中
}
}
vue 代码如下
let $page = usePage();
let mainData= useData('mainData'); //获取表格组件绑定的数据集
let selectData = useData('selectData'); //获取表格组件绑定的选中数据集
onMultiSelectTableRowClick = ({event,record,index}) => {
let selectedRowKeys = selectData.getIDs(); //获取当前选中的数据的主键列表
let idColumn = selectData.getIdColumn(); //获取选中数据集的主键列名
let rowId = record[idColumn]; //从表格当前行 record 中获取主键值
if(selectedRowKeys.indexOf(rowId) > -1){ //已选中,取消选中
selectData.removeData(rowId); //取消选中
}else{
mainData.copyRows(rowId,"selectData"); //未选中,设置为选中
}
}
特别说明:删除选中数据集的数据使用 removeData 方法,不能使用 deleteData 方法
- removeData 方法是前端删除数据组件中数据的方法,仅删除前端数据,不删除数据库中的数据
- deleteData 方法是删除数据集中数据的方法,即会发送请求从数据库中删除数据
删除选中的数据
删除选中时,选中数据集中的数据都是要删除的数据,通过"选中数据集"的"ID列表"方法获取要删除数据的主键列表,作为删除方法的参数,删除后清空选中数据集
操作设置如下图所示
用 JS 代码实现,代码如下
react 代码
onDeleteSelectBtnClick = (event) => {
let mainData = this.comp("mainData"); //获取表格组件绑定的数据集
let selectData = this.comp("selectData"); //获取表格组件绑定的选中数据集
mainData.deleteData(selectData.getIDs()).then(()=>{ //获取选中数据集的主键列表,删除数据
selectData.clear(); //删除后,清除选中数据集的数据
},()=>{});
}
vue 代码
let $page = usePage();
let mainData= useData('mainData'); //获取表格组件绑定的数据集
let selectData = useData('selectData'); //获取表格组件绑定的选中数据集
let onDeleteSelectBtnClick = (event) => {
mainData.deleteData(selectData.getIDs()).then(()=>{ //获取选中数据集的主键列表,删除数据
selectData.clear(); //删除后,清除选中数据集的数据
},()=>{});
}
冻结列(固定列)
对于列数很多的数据,可以固定前后的列,横向滚动查看其它数据,和“横向滚动宽度”配合使用。“横向滚动宽度”需要输入一个值,如下图所示。
列的“固定列”属性设置为“居左”,表示固定在表格左边,设置为“居右”,表示固定在表格右边。
如果设置了多选或单选,要控制多选或单选也固定,可以在表格组件的“选择功能配置”中设置“固定”为“是”,如下图所示
隐藏列
表格的列有动态隐藏属性,通过一个表达式控制列是显示还是隐藏,设计界面如下图所示
动态渲染列(48)
从48版本开始,表格组件增加渲染前事件,可用于动态渲染列,如下图所示,其中岗位工资、绩效工资、税、工龄工资4列是在渲染前事件中渲染出来的
设计界面如下图所示,备注说明后面就是操作列
岗位工资、绩效工资、税、工龄工资4列的数据在从表中,通过输出数据集返回 JSON 数据,如下图所示
JSON 数据格式如下图所示
渲染前事件代码如下,props.dataSource 就是返回的 JSON 数据,Column 的 dataIndex 指向 dataSource 中的 key 可以直接渲染出数据
onTableRender = (event) => {
let {detail:{props}} = event;
//完整遍历从表,获得动态渲染的列名,并将从表数据写入 dataSource 以便通过 dataIndex 的指定进行渲染
let itemName = [];
props.dataSource.map((item)=>{
item.detail && item.detail.map((item2)=>{
item[item2.itemName]=item2.money;
if (itemName.indexOf(item2.itemName) == -1) {
itemName.push(item2.itemName);
}
})
})
//在操作列前,插入列
for (let i in itemName) {
let index = props.children.length - 1;
props.children.splice(index,0,<Column title={itemName[i]} dataIndex={itemName[i]} key={itemName[i]} width={120}/>)
}
}
渲染前事件中 props 数据格式如下图所示
执行5到12行的代码后,将从表数据写入 dataSource ,数据如下图所示
Column 的 dataIndex 指向 dataSource 中的 key (例如:岗位工资),表格中就会显示出岗位工资列及数据
多列头
多列头使用列组实现,在表格中“添加列组”,在列组中“添加列”,即可显示为多列头。
总结栏
在表格中“添加总结栏”,在表格的下方出现一个空行,在行内的单元格中,可以放文本组件显示相关内容,也支持放其它组件。
显示数据组件中的记录数、某列的总和、平均值可以使用数据组件的函数,也可以自定义函数实现复杂计算,参考《页面表达式》
总结栏如果需要一直显示在表格底部,如下图所示
需要设置表格组件的“纵向滚动高度”,如下图所示,如果要实现表格充满的效果,参考《页面布局》中的充满布局
总结栏行的列合并
总结栏行列默认是跟表格上的列一一对应,如下显示
可以通过总结栏列上提供的跨列设置列合并,如设置为3即从第1列开始往后列表3列,需要注意设计时需要把总结栏中的第2列和第3列删除
设置后的运行效果如下:
固定表头
表格组件设置“纵向滚动高度”属性,实现表头固定效果。表头固定通常是页面在使用充满布局时的常见做法,关于页面使用充满布局,参考《页面布局》中讲解的充满布局,里面介绍了表格组件表头固定的实现方法。
嵌套表格
嵌套表格将两个或多个数据组件的数据,以嵌入在行下方的方式显示,支持展开和收起。
- 在外层表格中“添加子表格”
- 子表格绑定数据集、添加列、设置“过滤条件”
- 过滤条件中的行记录是子表格的数据
- 过滤条件设置为:子表格中的某列数据等于外层表格中的某列数据
特别说明:如果嵌套表格关联的两个数据组件,在后端设置了主从关系,必须清空页面上从数据组件的“主从选项”属性
- 主从选项使得从数据的数据,跟随主数据当前行的变化而重新加载,即从数据中只会显示一条主数据的从数据
- 去掉主从关系,使得从数据可以加载任意数据,表格中才能显示出多主多从的效果
表格单元格合并
在表格列的渲染函数中设置行合并数 rowSpan 的值,rowSpan 为2表示合并两行。
本例提供一个单元格合并的完整案例,合并数据中的“一级分类”列 c1_name、“二级分类”列 c2_name 和“三级分类”列 c3_name
- 在数据组件的刷新后事件中,根据数据组件中的数据,计算每行的一级分类、二级分类和三级分类需要合并的行数,形成 JSON 对象,存储到计算列 spanCount 中
- 在需要合并行的列(“一级分类”列、“二级分类”列和“三级分类”列)的渲染方法中,获取合并行数 spanCount,赋值给渲染方法返回值 rowSpan
开发过程如下:
计算合并列
- 数据组件添加计算列:spanCount,文本类型,要存储 JSON 字符串
- 在数据组件的刷新后事件中,根据数据计算合并行数
JS 代码如下:
onRowSpanDataAfterRefresh = (event) => {
// 初始化计算列 spanCount
let data = event.source;
// spanCols 指定要合并的列,支持多列,列的合并行数会记录在计算列 spanCount 中
let spanCols = ["c1_name","c2_name","c3_name"];
let firstRow = {};
// 解析并写入计算列 spanCount = "{c1_name:4,c2_name:2,c3_name:1}"
function setSpanCount(row, col, count) {
let spanCount = {};
if (row.spanCount) {
spanCount = JSON.parse(row.spanCount);
}
spanCount[col] = count;
data.setValue("spanCount", JSON.stringify(spanCount), row);
}
// 遍历数据
data.each(function(params){
let row = params.row;
for (let i = 0; i < spanCols.length; i++) {
let spanCol = spanCols[i];
let value = row[spanCol];
if (firstRow[spanCol] && (value == firstRow[spanCol].value)) {
// 如果当前列的值在 firstRow 已存在,首行的合并数 + 1,当前行的合并数 = 0
firstRow[spanCol].count = firstRow[spanCol].count + 1;
setSpanCount(row, spanCol, 0);
} else {
// 如果当前列的值在 firstRow 不存在
if (firstRow[spanCol]) {
// 记录前一个值的首行合并数
setSpanCount(firstRow[spanCol].firstRow, spanCol, firstRow[spanCol].count)
}
// 开始记录下一个值的首行
firstRow[spanCol] = {
"firstRow": row,
"value": value,
"count": 1
}
}
}
})
// 遍历后记录最后的首行
for (let i = 0; i < spanCols.length; i++) {
let spanCol = spanCols[i];
setSpanCount(firstRow[spanCol].firstRow, spanCol, firstRow[spanCol].count)
}
}
react 列渲染
- 添加“一级分类”列、“二级分类”列、“三级分类”列的渲染方法
JS 代码如下:
//一级分类列的渲染方法
tableColumn26RenderRender = (text, record, index) => {
return this.columnRender(text, record, index, "c1_name");
}
//二级分类列的渲染方法
tableColumn27RenderRender = (text, record, index) => {
return this.columnRender(text, record, index, "c2_name");
}
//三级分类列的渲染方法
tableColumn28RenderRender = (text, record, index) => {
return this.columnRender(text, record, index, "c3_name");
}
//合并列的渲染
columnRender(text, record, index, col) {
// 获取表格当前行-指定列的合并数
let spanCount = this.comp("rowSpanData").getValue("spanCount", record);
return {
children: text,
props: {
rowSpan: spanCount ? JSON.parse(spanCount)[col] : 1
}
};
}
特别说明 渲染方法用于返回 ReactNode,表格列渲染方法返回 JSON 数据,因此需要手工修改 w 文件
将系统生成的代码,<attr:render/>
<antdpro:Table.Column class="column c-columnMiddle" dataIndex="c1_name" id="tableColumn26" width="120px" xmlns:attr="http://www.wex5.com/attr">
<attr:title id="default68">
<antdpro:Typography.Text id="typographyText31" text="一级分类"/>
</attr:title>
<attr:render d_canAddChild="false" designer_child_type="code" id="default75">
<Fragment id="fragment0">{$page.tableColumn26RenderRender(text, record, index)}</Fragment>
</attr:render>
</antdpro:Table.Column>
修改为 render 属性
<antdpro:Table.Column class="column c-columnMiddle" dataIndex="c1_name" id="tableColumn26" render="{$page.tableColumn26RenderRender(text, record, index)}" width="120px" xmlns:attr="http://www.wex5.com/attr">
<attr:title id="default68">
<antdpro:Typography.Text id="typographyText31" text="一级分类"/>
</attr:title>
</antdpro:Table.Column>
vue 列渲染
切换到源码,在“一级分类”列、“二级分类”列、“三级分类”列中添加 customRender="{columnRender}"
,添加后完整代码如下
<antdv:Table.Column class="column" customRender="{columnRender}" dataIndex="c1_name" id="tableColumn27" width="120px" xmlns:attr="http://www.wex5.com/attr">
<attr:title d_canAddChild="true" id="default70">
<antdv:Typography.Text content="一级分类" id="typographyText30"/>
</attr:title>
</antdv:Table.Column>
在 js 文件中添加 columnRender 方法,代码如下
//合并列的渲染
let columnRender = ({text, record, index, column}) => {
// 获取表格当前行-指定列的合并数
let spanCount = rowSpanData.getValue("spanCount", record);
return {
children: text,
props: {
rowSpan: spanCount ? JSON.parse(spanCount)[column.dataIndex] : 1
}
};
}
拖拽行(React 表格支持,Vue 表格不支持)
React 表格支持拖拽行,实现调整行顺序的效果。设置表格的“拖拽行排序”属性为是,表格左边第一列会显示一个三横图标,用鼠标拖拽这个图标,实现拖拽行的效果。拖动到期望的位置后松开鼠标,触发“行拖拽后事件”。
在“行拖拽后事件”中,调用数据组件的 moveTo 方法移动行,界面上就显示出移动的效果。
本例移动后修改相关行的序号列的值,“行拖拽后事件”的 JS 代码如下:
constructor(props, context) {
super(props, context);
this.sortDataId = "mainData";//拖拽排序数据组件id
this.sortDataIdCol = "fid";//拖拽排序数据组件主键列名
this.sortNoCol = "sortNo";//拖拽排序数据组件序号列名
}
/*-------------------拖拽排序-------------------*/
onTable6DragSort = ({active,over}) => {
let mainData = this.comp(this.sortDataId);
//获得移动行
let srcRow = mainData.getRowByID(active.id);
//获得目标行
let tarRow = mainData.getRowByID(over.id);
//获得id数组,移动行索引,目标行索引
let idArr = active.data.current.sortable.items;
let begin = active.data.current.sortable.index;
let end = over.data.current.sortable.index;
//获得移动方向
let up = begin > end;
//移动
mainData.moveTo(srcRow,tarRow,up?"BEFORE":"AFTER");
//备份目标行的序号
let sortEnd = this.getSortById(idArr[end]);
if(up){
//从over到active-1的新序号 是下一行的序号
for(let i=end;i<begin;i++){
let sort = this.getSortById(idArr[i+1]);
mainData.setValueByID(this.sortNoCol,sort,idArr[i]);
}
}else{
//从over到active-1的新序号 是上一行的序号
for(let i=end;i>begin;i--){
let sort = this.getSortById(idArr[i-1]);
mainData.setValueByID(this.sortNoCol,sort,idArr[i]);
}
}
//active的新序号 是 over的序号
mainData.setValueByID(this.sortNoCol,sortEnd,idArr[begin]);
}
getSortById = (id) => {
let row = this.comp(this.sortDataId).find([this.sortDataIdCol],[id]);
if(row.length > 0){
return row[0].sortNo;
}
}
表格布局属性
列内容不换行,会导致列宽被撑宽,影响列的布局,如下图所示
设置“表格元素的 table-layout”属性为“固定”表示内容不会影响列的布局,设计界面如下图所示
运行效果如下图所示
树形表格
表格组件绑定树形数据,会在第一列显示展开箭头,用于逐级展开树形数据,如下图所示
树组件
树和表格组件不同,树只展示一列,且不显示列头,如下图所示
树展示哪一列数据,由树组件的“显示列”属性指定
默认展开
树支持默认展开全部和默认展开根
- “默认展开”属性设置为“展开全部”:树组件显示数据组件中的全部数据,如果数据组件中数据不全,不会发送请求取数据,即树组件仅在加载全部数据后,才能呈现展开全部的效果
- “默认展开”属性设置为“展开根”:树组件发送请求,加载第一个节点的数据,并展开显示,如下图所示
树过滤
树组件绑定的数据组件配置了全路径ID和全路径名称时,搭配智能过滤组件,可以实现树过滤,运行效果如下图所示
多选
树支持勾选和级联勾选
- “勾选”属性设置为“是”:树的展开箭头右侧显示一个多选框,用于多选,和表格多选一样,在设置“选中数据集”属性后,选中的数据写入选中数据集
- “级联勾选”属性设置为“是”:选中父节点,自动选中全部子节点;选中全部子节点,自动选中父节点
- “级联勾选”属性设置为“否”:选中节点,不自动选中其他节点
特别说明
- 选中数据集为树形数据时,编辑该数据组件,取消勾选“树形数据”,作为普通数据使用
显示图标
树组件除了展开/折叠图标以外,在标题前面还可以显示一个图标,运行效果如下图所示
设置“显示图标”属性为“是”,在“节点图标”属性中根据不同的数据显示不同的图标,设计界面如下图所示
使用单色图标(线框风格和实底风格)时,使用下面的写法定义图标颜色,引号必须使用 \" 转义
"css:{"color":"orange"}@gift,outlined"
使用双色图标时,在设计界面中可以选择主色,如下图所示
另外还提供“节点样式”属性,为节点(包括图标和标题)设置 class 名称
例如:给图标设置颜色,vue 的 css 定义如下
:deep {
.x-orange .ant-tree-iconEle {
color: orange;
}
}
用代码选中虚根
写 JS 代码选中虚根,代码如下
let tree = this.comp("tree");
tree.setSelection("__VIRTUAL_ROOT__")
列表组件
列表组件和表格组件一样,同样是展示数据组件的全部数据,不同的是,表格组件一行显示一条数据,列表组件则没有限制,即可以一行显示一条数据、也可以一行显示多条数据(如下图所示)、还可以多行显示一条数据。
列表项
列表组件提供一种固定格式:列表项。包括图标、标题、描述、内容区、扩展区、操作栏,支持垂直和水平两种布局方式。组件层次结构,如下图所示
垂直布局,展示效果示意图,如下图所示
水平布局,展示效果示意图,如下图所示
垂直布局,实际运行效果,如下图所示
水平布局,实际运行效果,如下图所示
布局方式
列表组件组件除了支持列表项,也支持在列表中添加任意组件。
- 列表模板中只有一个组件时
- 组件是行级元素,则一行显示一个
- 组件是行内元素,则流式布局,一行显示多个
- 列表模板中超过一个组件时,列表的展示方向支持“水平”和“垂直”
垂直列表
列表的“方向”属性设置为“垂直”,系统自动增加一个 div 节点,用于实现行级元素效果,如下图所示
水平列表
列表的“方向”属性设置为“水平”,系统自动增加一个 span 节点,用于实现行内元素效果,如下图所示
固定列数
在列表的“列表栅格配置-列数”属性中设置数字,列表显示为一行显示多个数据的效果,设置界面如下图所示
运行效果如下图所示
响应式
列表通过“列表栅格配置”实现响应式布局,即在不同的分辨率下,列表中一行显示的个数可以不同,且不受24栅格的影响,个数支持任意整数。设置界面如下图所示
运行效果如下图所示
嵌套列表
嵌套列表和嵌套表格一样,都是内层列表或表格设置“过滤条件”即可。因此对于嵌套需求,支持表格嵌套表格、表格嵌套列表、列表嵌套列表、列表嵌套表格
- 在外层列表中添加“列表”组件,作为内层列表
- 内层列表绑定数据集、设置“过滤条件”
- 过滤条件中的行记录是内层列表的数据
- 过滤条件设置为:内层列表中的某列数据等于外层列表中的某列数据
运行效果如下图所示
特别说明:如果嵌套列表关联的两个数据组件,在后端设置了主从关系,必须清空页面上从数据组件的“主从选项”属性
- 主从选项使得从数据的数据,跟随主数据当前行的变化而重新加载,即从数据中只会显示一条主数据的从数据
- 去掉主从关系,使得从数据可以加载任意数据,列表中才能显示出多主多从的效果
加载方式
数据组件加载下一页数据时,有两种方式,一种是清空现有数据,加载新数据,另一种是保留现有数据,追加新数据。
- 列表组件不设置“加载方式”,配合“分页”组件,实现第一种加载效果
- 列表组件设置“加载方式”为“点击加载”,不需要使用“分页”组件,运行时,在列表最后显示“加载更多”按钮,点击“加载更多”按钮,追加下一页数据
- 列表组件设置“加载方式”为“滚动加载”,不需要使用“分页”组件,运行时,通过鼠标滚轮的向下滚动,追加下一页数据。滚动分页需要在列表上增加 height 和 overflow 两个样式,设置界面如下图所示
样式代码如下
.c-scroll-list{
height: calc(100vh - var(--x-portal-header-height) - 80px);
overflow: auto;;
}
使用案例
表格-显示序号
表格组件中可以显示两种序号,一种是每页都从1开始,另一种是所有数据大排序,第一页从1开始,第二页继续前一页的序号,如下面两张图所示
表格序号
使用表格当前序号实现,在列渲染中添加文本组件,设置“文本”属性为:表格当前序号 + 1
跨页序号
跨页序号使用数据组件的跨页序号方法实现。
- 给数据组件添加一个计算列,用于计算、存储、显示跨页序号
- 设置计算列的计算规则,为数据组件的跨页序号方法,数据组件为每一行的计算列写入一个递增的序号
- 在表格中添加计算列,显示跨页序号
表格-控制显示加载中
在页面中执行数据加载、通过 this.request 发送请求时,页面组件会根据执行时间,自动显示加载遮罩,一般情况不需要开发者关心加载遮罩。如果确实需要自己控制表格的加载遮罩,在表格中增加“加载中配置”,将“加载中”属性绑定一个数据列,根据数据列中的值控制是否显示加载遮罩。
表格-行内按钮事件
使用表格当前行数据
在表格组件的列渲染中的按钮,在添加事件前,开启扩展参数,设置“参数名称”,选择“参数值”。
参数值可以选择“渲染”中的“文本”、“行对象”、“索引”、“表格当前序号”、“表格当前行”。其中“行对象”和“表格当前行”是一样的,前者是 Antd 提供的渲染回调方法的参数,后者是平台提供的语法糖。
事件跳转后生成 JS 方法,包括扩展参数,代码如下:
onEditBtnClick = ({row}) => (event) => {
message.info(row.name); //获取行对象中name列的值
event.stopPropagation(); //阻止冒泡
}
阻止冒泡
在表格组件中,即设置了列渲染中按钮的点击事件,也设置了行点击事件,运行时点击按钮,会前后触发按钮的点击事件和行点击事件,这种事件向父节点传递称为冒泡,在事件中执行 event.stopPropagation(); 语句可以阻止向上冒泡,代码如下
onEditBtnClick = ({row}) => (event) => {
message.info(row.name); //获取行对象中name列的值
event.stopPropagation(); //阻止冒泡
}
表格-当前行样式
有些时候,表格组件上需要显示出刚点击过的行。例如主从两个表格,点击主表格的某行,从表格中显示主数据对应的从数据,此时需要在主表格中明确显示出从数据对应的主数据。
表格组件提供“当前行类名”属性,可以设置为“高亮效果”或自定义的类名,高亮效果使用的是表格组件的选中类名 ant-table-row-selected
ant-table-row-selected 类运行效果如下图所示
如果需要修改系统默认的样式,有两种方法,一种是使用 css 代码修改样式,另一种是使用主题配置修改样式,推荐使用第二种方法。
react 使用 css 代码修改样式
使用下面的 css 代码,全局修改选中行的背景色
:global{
.ant-table-wrapper .ant-table-tbody .ant-table-row.ant-table-row-selected >.ant-table-cell{
background-color: pink;
}
}
使用下面的 css 代码,修改具有 c-custom 样式的节点下的表格选中行的背景色
.c-custom{
:global{
.ant-table-wrapper .ant-table-tbody .ant-table-row.ant-table-row-selected >.ant-table-cell{
background-color: pink;
}
}
}
运行效果如下图所示
- 当前应用若是从门户应用打开的,且需要修改全局样式,请使用主题配置修改样式
- 当前应用若是独立运行,可以将上面的 css 代码写在 UI2/pcx/common.css 文件中,在 UI2/pcx/common.js 文件中引用 common.css,代码如下。系统运行时会自动引用 common.js,从而引用了 common.css,使得运行系统后,样式立即生效
import "./common.css";
vue 使用 css 代码修改样式
使用下面的 css 代码,修改当前页面所有表格组件的选中行的背景色
.x-page {
:deep{
.ant-table-wrapper .ant-table-tbody >tr.ant-table-row-selected >td{
background-color: pink;
}
}
}
具体组件样式的修改可以参考《页面样式》中的说明
使用主题配置修改样式
系统支持主题(皮肤)配置,在主题配置中定义 Antd 全局 Token、组件的 Token、组件的样式、非组件的样式、iframe 嵌入页面的样式,具体使用参考《主题配置》中的“表格当前行样式修改案例”。
表格-接管列头排序
点击表格的某列,对该列进行排序。如果该列关联的是 restData 的实体列,则系统可对其进行排序处理。如果该列没有对应 restData 的某个实体列,或者关联的是 serviceData,则需要写代码实现排序。例如:下图中“二级+三级”列是数据集中“二级”列和“三级”列组合起来的
二级+三级的列定义如下
<antdv:Table.Column xmlns:attr="http://www.wex5.com/attr" class="column" dataIndex="fself" id="tableColumn3" width="120px" sorter="{{"compare":false}}">
<attr:title id="default8">
<antdv:Typography.Text content="二级+三级" id="typographyText3"/>
</attr:title>
<attr:render id="default9"/>
</antdv:Table.Column>
接管表格组件的“配置改变” onChange 事件,从事件参数中获取点击的列 sorter.field,以及排序方式 sorter.order。
其他列的排序由系统处理,本事件中只处理点击二级+三级列的排序,代码如下:
import { reactive, ref, watch } from "vue";
import { usePage, useData } from "vue_addon/core";
let $page = usePage();
let data = useData("restData0");//restData0是表格绑定的数据集的id
let onTable0Change = ({pagination,filters,sorter,extra}) => {
// 只处理fself字段的排序
if(sorter.field != "fself") return;
// 获取数据集上定义的排序
if(!$page.cloneOrd){
let baseOrders = data.getOderBysObj();
if (baseOrders && baseOrders.length > 0) {
$page.cloneOrd = [...baseOrders]
}
}
// 清空排序
data.clearOrderBy();
let order = sorter.order;
order = 'ascend' === order ? 1 : ('descend' === order ? 0 : undefined);
data.setOrderBy("ferji", order);
data.setOrderBy("fsanji", order);
// 把数据集上定义的排序追加在后面
if ($page.cloneOrd && $page.cloneOrd.length > 0) {
for (let i in $page.cloneOrd) {
data.setOrderBy($page.cloneOrd[i].name,$page.cloneOrd[i].type);
}
}
data.refreshData();
}
表格-表头固定、总结栏固定
表头和总结栏如果需要一直显示在表格头部和底部,如下图所示
需要设置表格组件的“纵向滚动高度”,如下图所示,如果要实现表格充满的效果,参考《页面布局》中的充满布局
表格-设置空图片
当表格无数据时,Antd 默认显示为下图
希望改为自定义的图片和文字内容,如下图所示
通过设置 css 实现,隐藏原来的图片和文字,通过设置背景图显示新的图片,通过增加 after 伪类显示新的文字内容。实现步骤如下
- 上传图片
依次点击“页面-设置-素材库”,打开素材库对话框,上传图片至 UI2/pcx/images 目录下。
本例中上传 empty.svg 文件.
- 在 css 文件中,增加下面的 css
.custom{
:deep{
.ant-empty.ant-empty-normal .ant-empty-image {
background-image: url(./images/empty.svg);
background-repeat: no-repeat;
background-position: top center;
background-size: 276px 128px;
margin-bottom: 16px;
height: 128px;
}
.ant-empty.ant-empty-normal .ant-empty-description,
.ant-empty.ant-empty-normal .ant-empty-image svg{
display: none
}
.ant-empty.ant-empty-normal:after {
content: "暂无内容";
font-size: 14px;
color: rgba(0, 0, 0, 0.45);
}
}
}
}
在页面组件的预定义样式上添加 custom,实现自定义空图片和文字的效果
- 不同的表格显示不同的空图片
上面的写法是当前页面中全局生效的,要实现不同的表格显示不同的空图片,使用下面的方式定义 css
.task-table{
:global(.ant-empty.ant-empty-normal .ant-empty-image){
background-image: url(./images/empty.svg);
background-repeat: no-repeat;
background-position: top center;
background-size: 276px 128px;
margin-bottom: 16px;
height: 128px;
}
:global(.ant-empty.ant-empty-normal .ant-empty-description,
.ant-empty.ant-empty-normal .ant-empty-image svg){
display: none
}
:global(.ant-empty.ant-empty-normal:after) {
content: "暂无内容";
font-size: 14px;
color: rgba(0, 0, 0, 0.45);
}
}
.notice-table{
:global(.ant-empty.ant-empty-normal .ant-empty-image){
background-image: url(./images/empty.svg);
background-repeat: no-repeat;
background-position: top center;
background-size: 276px 128px;
margin-bottom: 16px;
height: 128px;
}
:global(.ant-empty.ant-empty-normal .ant-empty-description,
.ant-empty.ant-empty-normal .ant-empty-image svg){
display: none
}
:global(.ant-empty.ant-empty-normal:after) {
content: "暂无内容";
font-size: 14px;
color: rgba(0, 0, 0, 0.45);
}
}
在表格外层增加区块组件,设置自定义样式为 task-table,使用 task-table 里面的样式;定义为 notice-table,使用 notice-table 里面的样式。
树形表格-展开
树形表格的展开需要使用系统组件 ExpandedData 提供的展开全部 expandAll 和收起全部 collapseAll 两个方法。需要说明的是,展开全部方法不发送请求,只是将数据组件中的数据全部显示,即有多少数据显示多少数据
使用 ExpandedData 组件,需要引用,代码如下
import ExpandedData from "$UI/wxsys/comps/expandedData/ExpandedData";
ExpandedData 组件提供 getInstance 方法获取数据组件的展开数据实例,说明如下
方法:
getInstance ({Data: refData})
描述:
获取组件实例
参数:
refData:{Data} - 数据组件对象
返回值:
ExpandedData
ExpandedData 组件提供 expandAll 方法展开全部数据,说明如下
方法:
expandAll ()
描述:
将数据组件中的数据全部展开显示
ExpandedData 组件提供 collapseAll 方法收起全部数据,说明如下
方法:
collapseAll ()
描述:
收起后,只显示根节点
示例代码
import ExpandedData from "$UI/wxsys/comps/expandedData/ExpandedData";
//展开所有
onExpandAllBtnClick = (event) => {
ExpandedData.getInstance({refData:this.comp('restData1')}).expandAll();
}
//关闭所有
onCollapseAllBtnClick = (event) => {
ExpandedData.getInstance({refData:this.comp('restData1')}).collapseAll();
}
运行效果如下图所示
树形表格-自定义展开图标
树形表格默认的展开图标是箭头,在“树形展开配置”提供的有“展开图标”的设置可以自定义展开图标
"展开图标"是点击"跳转"生产js函数,通过js实现的。需要在js中引入需要使用的图标,如下:
react代码
import {PlusSquareOutlined, MinusSquareOutlined } from '@ant-design/icons';
vue代码
import {PlusSquareOutlined, MinusSquareOutlined} from '@ant-design/icons-vue';
具体"展开图标"函数的实现如下:
react代码
tableExpandable0ExpandIconFn = (props) => {
if (!props.expandable) {
return <span className={"antd-table-tree-expand-icon"} />;
}
if (props.expanded) {
return <MinusSquareOutlined className={"antd-table-tree-expand-icon"} onClick={e => {
props.onExpand(props.record, e);
e.stopPropagation();
}}/>;
} else {
return <PlusSquareOutlined className={"antd-table-tree-expand-icon"} onClick={e => {
props.onExpand(props.record, e);
e.stopPropagation();
}}/>;
}
}
vue代码
let tableExpandable0ExpandIconFn = (props) => {
if (!props.expandable) {
return <span class={"antd-table-tree-expand-icon"} />;
}
if (props.expanded) {
return <MinusSquareOutlined class={"antd-table-tree-expand-icon"} onClick={e => {
props.onExpand(props.record, e);
e.stopPropagation();
}} />;
} else {
return <PlusSquareOutlined class={"antd-table-tree-expand-icon"} onClick={e => {
props.onExpand(props.record, e);
e.stopPropagation();
}} />;
}
}
运行效果如下:
树-展开
树组件提供展开全部和展开某行的方法
- 展开全部
树组件提供 expandAll 方法显示数据组件中的全部数据,调用示例代码如下:
react 代码
let onButton5Click = (event) => {
this.comp("tree0").expandAll();
}
vue 代码
let onButton5Click = (event) => {
$page.comp("tree0").expandAll();
}
特别说明
- 如果要全展开就需要数据组件加载全部数据,如果只加载了根数据只会显示根,即加载了多少数据就会显示多少数据
- 展开具体的行
树组件提供 expandNode(id) 方法展开行,参数是行的主键值,调用示例代码如下
react 代码
let onButton6Click = (event) => {
this.comp("tree0").expandNode("CA8A602D66400001D1DC1C10E5109CC0");
}
vue 代码
let onButton6Click = (event) => {
$page.comp("tree0").expandNode("CA8A602D66400001D1DC1C10E5109CC0");
}
特别说明
- 如果数据组件中没有展开行数据,显示不出展开的效果,即不能展开一个不在树上的节点
列表类组件
列表类组件提供很多属性用于界面展现和用户交互,鉴于官网介绍的比较详细,本文不再赘述。
组件 | 用途 | Antd 官网 | Antd Vue 官网 |
---|---|---|---|
表格 | 展示行列数据 | 表格 | 表格 |
树 | 多层次的结构列表 | 树 | 树 |
列表 | 最基础的列表展示,可承载文字、列表、图片、段落 | 列表 | 列表 |
分页 | 分页器用于分隔长列表,每次只加载一个页面 | 分页 | 分页 |
案例位置
桌面-页面-列表表单组件-表格组件.w、列表组件.w、树形组件.w