跳到主要内容
Data Table
表格是一种常见的信息展现形式,它是所有B端组件中信息展示密度最高,涵盖场景面最广,信息结构最复杂的一种数据结构形式,数据表格用于显示一些结构化的数据,用户可以看到表格的行和列,以及表头、分页、排序、筛选等功能,并可以对表格中的数据进行交互操作。

示例

数据表格快捷键

仅在 selectable 情况下支持

  • 上下方向键切换行,需要手动选中一行
  • 高亮行回车默认触发 enter 事件,
  • 空格键当前行选中或者取消选中

静态数据

PCPhonePad

<page>
<table data="{{tableData}}" height="auto">
<x-cell label="日期">
{{cellData.rowData.date}}
</x-cell>
<x-cell label="姓名">
{{cellData.rowData.name}}
</x-cell>
<x-cell label="地址">
{{cellData.rowData.address}}
</x-cell>
</table>
</page>

export default XPage({
data: {
tableData: [{
date: '2016-05-02',
name: '王小虎',
address: '上海市普陀区金沙江路 1518 弄'
}, {
date: '2016-05-04',
name: '王小虎',
address: '上海市普陀区金沙江路 1517 弄'
}, {
date: '2016-05-01',
name: '王小虎',
address: '上海市普陀区金沙江路 1519 弄'
}, {
date: '2016-05-03',
name: '王小虎',
address: '上海市普陀区金沙江路 1516 弄'
}]
}
});

数据趋势

PCPhonePad
<page>
<table data="{{tableData}}" height="auto">
<x-cell label="上升趋势(chartup)">
<x-datacell type="chartup" :data="cellData.rowData.chartup"/>
</x-cell>
<x-cell label="下降趋势(chartdown)">
<x-datacell type="chartdown" :data="cellData.rowData.chartdown"/>
</x-cell>
<x-cell label="条形图(bar)">
<x-datacell type="bar" :data="cellData.rowData.bar"/>
</x-cell>
<x-cell label="圆环(cycle)">
<x-datacell type="cycle" :data="cellData.rowData.cycle"/>
</x-cell>
</table>
</page>

export default XPage({
data: {
tableData: [
{
chartup:'80',
chartdown:'80',
bar:'80',
cycle:'80',
},
{
chartup:'70',
chartdown:'70',
bar:'70',
cycle:'70',
},
{
chartup:'60',
chartdown:'60',
bar:'60',
cycle:'60',
}
]
}
});


x-datacell标签支持在表格内展示数据趋势,type支持chartup chartdown bar cycle四种类型 data 值为数字,目前仅建议使用在table内

左右吸附

PCPhonePad

<page>
<x-table data="{{tableData}}" height="200px">
<x-cell label="No." fixed="left">
{{cellData.rowIndex+1}}
</x-cell>
<x-cell label="日期">
{{cellData.rowData.date}}
</x-cell>
<x-cell label="姓名">
{{cellData.rowData.name}}
</x-cell>
<x-cell label="省/直辖市">
{{cellData.rowData.province}}
</x-cell>
<x-cell label="市区">
{{cellData.rowData.city}}
</x-cell>
<x-cell label="详细地址">
{{cellData.rowData.address}}
</x-cell>
<x-cell label="邮编">
{{cellData.rowData.zip}}
</x-cell>
<x-cell label="学历">
{{cellData.rowData.education}}
</x-cell>
<x-cell label="职业">
{{cellData.rowData.occupation}}
</x-cell>
<x-cell label="操作" fixed="right">
<x-button text="编辑"></x-button>
<x-button text="操作"></x-button>
</x-cell>
</x-table>
</page>

export default XPage({
data: {
tableData: [{
date: '2016-05-03',
name: '王小虎',
province: '上海',
city: '普陀区',
address: '上海市普陀区金沙江路 1518 弄',
zip: 200333,
education: '本科',
occupation: "前端工程师"
}, {
date: '2016-05-02',
name: '王小虎',
province: '上海',
city: '普陀区',
address: '上海市普陀区金沙江路 1518 弄',
zip: 200333,
education: '本科',
occupation: "前端工程师"
}, {
date: '2016-05-04',
name: '王小虎',
province: '上海',
city: '普陀区',
address: '上海市普陀区金沙江路 1518 弄',
zip: 200333,
education: '本科',
occupation: "前端工程师"
}, {
date: '2016-05-01',
name: '王小虎',
province: '上海',
city: '普陀区',
address: '上海市普陀区金沙江路 1518 弄',
zip: 200333,
education: '本科',
occupation: "前端工程师"
}, {
date: '2016-05-08',
name: '王小虎',
province: '上海',
city: '普陀区',
address: '上海市普陀区金沙江路 1518 弄',
zip: 200333,
education: '本科',
occupation: "前端工程师"
}, {
date: '2016-05-06',
name: '王小虎',
province: '上海',
city: '普陀区',
address: '上海市普陀区金沙江路 1518 弄',
zip: 200333,
education: '本科',
occupation: "前端工程师"
}, {
date: '2016-05-07',
name: '王小虎',
province: '上海',
city: '普陀区',
address: '上海市普陀区金沙江路 1518 弄',
zip: 200333,
education: '本科',
occupation: "前端工程师"
}, {
date: '2016-05-03',
name: '王小虎',
province: '上海',
city: '普陀区',
address: '上海市普陀区金沙江路 1518 弄',
zip: 200333,
education: '本科',
occupation: "前端工程师"
}, {
date: '2016-05-02',
name: '王小虎',
province: '上海',
city: '普陀区',
address: '上海市普陀区金沙江路 1518 弄',
zip: 200333,
education: '本科',
occupation: "前端工程师"
}, {
date: '2016-05-04',
name: '王小虎',
province: '上海',
city: '普陀区',
address: '上海市普陀区金沙江路 1518 弄',
zip: 200333,
education: '本科',
occupation: "前端工程师"
}, {
date: '2016-05-01',
name: '王小虎',
province: '上海',
city: '普陀区',
address: '上海市普陀区金沙江路 1518 弄',
zip: 200333,
education: '本科',
occupation: "前端工程师"
}, {
date: '2016-05-08',
name: '王小虎',
province: '上海',
city: '普陀区',
address: '上海市普陀区金沙江路 1518 弄',
zip: 200333,
education: '本科',
occupation: "前端工程师"
}, {
date: '2016-05-06',
name: '王小虎',
province: '上海',
city: '普陀区',
address: '上海市普陀区金沙江路 1518 弄',
zip: 200333,
education: '本科',
occupation: "前端工程师"
}, {
date: '2016-05-07',
name: '王小虎',
province: '上海',
city: '普陀区',
address: '上海市普陀区金沙江路 1518 弄',
zip: 200333,
education: '本科',
occupation: "前端工程师"
}]
}
});

selectable 可选择

PCPhonePad

<page>
<x-button text="选中第一个" bindclick="choose(0)"></x-button>
<x-button text="选中最后个" bindclick="choose(13)"></x-button>
<x-button text="获取选中数据" bindclick="showSelect"></x-button>
<x-table x="table" :data="tableData" height="200px" selectable>
<x-cell label="No." fixed="left">
{{cellData.rowIndex+1}}
</x-cell>
<x-cell label="日期">
{{cellData.rowData.date}}
</x-cell>
<x-cell label="姓名">
{{cellData.rowData.name}}
</x-cell>
<x-cell label="省/直辖市">
{{cellData.rowData.province}}
</x-cell>
<x-cell label="市区">
{{cellData.rowData.city}}
</x-cell>
<x-cell label="详细地址">
{{cellData.rowData.address}}
</x-cell>
<x-cell label="邮编">
{{cellData.rowData.zip}}
</x-cell>
<x-cell label="学历">
{{cellData.rowData.education}}
</x-cell>
<x-cell label="职业">
{{cellData.rowData.occupation}}
</x-cell>
<x-cell label="操作" fixed="right">
<x-button text="编辑"></x-button>
<x-button text="操作"></x-button>
</x-cell>
</x-table>
</page>

export default XPage({
data: {
tableData: [{
date: '2016-05-03',
name: '王小虎',
province: '上海',
city: '普陀区',
address: '上海市普陀区金沙江路 1518 弄',
zip: 200333,
education: '本科',
occupation: "前端工程师"
}, {
date: '2016-05-02',
name: '王小虎',
province: '上海',
city: '普陀区',
address: '上海市普陀区金沙江路 1518 弄',
zip: 200333,
education: '本科',
occupation: "前端工程师"
}, {
date: '2016-05-04',
name: '王小虎',
province: '上海',
city: '普陀区',
address: '上海市普陀区金沙江路 1518 弄',
zip: 200333,
education: '本科',
occupation: "前端工程师"
}, {
date: '2016-05-01',
name: '王小虎',
province: '上海',
city: '普陀区',
address: '上海市普陀区金沙江路 1518 弄',
zip: 200333,
education: '本科',
occupation: "前端工程师"
}, {
date: '2016-05-08',
name: '王小虎',
province: '上海',
city: '普陀区',
address: '上海市普陀区金沙江路 1518 弄',
zip: 200333,
education: '本科',
occupation: "前端工程师"
}, {
date: '2016-05-06',
name: '王小虎',
province: '上海',
city: '普陀区',
address: '上海市普陀区金沙江路 1518 弄',
zip: 200333,
education: '本科',
occupation: "前端工程师"
}, {
date: '2016-05-07',
name: '王小虎',
province: '上海',
city: '普陀区',
address: '上海市普陀区金沙江路 1518 弄',
zip: 200333,
education: '本科',
occupation: "前端工程师"
}, {
date: '2016-05-03',
name: '王小虎',
province: '上海',
city: '普陀区',
address: '上海市普陀区金沙江路 1518 弄',
zip: 200333,
education: '本科',
occupation: "前端工程师"
}, {
date: '2016-05-02',
name: '王小虎',
province: '上海',
city: '普陀区',
address: '上海市普陀区金沙江路 1518 弄',
zip: 200333,
education: '本科',
occupation: "前端工程师"
}, {
date: '2016-05-04',
name: '王小虎',
province: '上海',
city: '普陀区',
address: '上海市普陀区金沙江路 1518 弄',
zip: 200333,
education: '本科',
occupation: "前端工程师"
}, {
date: '2016-05-01',
name: '王小虎',
province: '上海',
city: '普陀区',
address: '上海市普陀区金沙江路 1518 弄',
zip: 200333,
education: '本科',
occupation: "前端工程师"
}, {
date: '2016-05-08',
name: '王小虎',
province: '上海',
city: '普陀区',
address: '上海市普陀区金沙江路 1518 弄',
zip: 200333,
education: '本科',
occupation: "前端工程师"
}, {
date: '2016-05-06',
name: '王小虎',
province: '上海',
city: '普陀区',
address: '上海市普陀区金沙江路 1518 弄',
zip: 200333,
education: '本科',
occupation: "前端工程师"
}, {
date: '2016-05-07',
name: '王小虎',
province: '上海',
city: '普陀区',
address: '上海市普陀区金沙江路 1518 弄',
zip: 200333,
education: '本科',
occupation: "前端工程师"
}]
},
choose(num) {
this.getComponent('table').select(num);
},

showSelect() {
const data = this.getComponent('table').getData();

console.log('打开控制台产看当前数据', data);

let [first] = data.selected;

alert(`当前选中行${++first}`);
}
});


selectable 默认选中

PCPhonePad

<page class="demo-box">
<x-button text="重置" bindclick="refresh"></x-button>
<x-table key="{{tableKey}}" x="table" data="{{tableData}}" height="200px" selectable="{{multiple:true}}" bindrendered=tableRendered beforeRequest="{{beforeRequest}}">
<x-cell label="No." fixed="left">
{{cellData.rowIndex+1}}
</x-cell>
<x-cell label="日期">
{{cellData.rowData.date}}
</x-cell>
<x-cell label="姓名">
{{cellData.rowData.name}}
</x-cell>
<x-cell label="省/直辖市">
{{cellData.rowData.province}}
</x-cell>
<x-cell label="市区">
{{cellData.rowData.city}}
</x-cell>
<x-cell label="详细地址">
{{cellData.rowData.address}}
</x-cell>
<x-cell label="邮编">
{{cellData.rowData.zip}}
</x-cell>
<x-cell label="学历">
{{cellData.rowData.education}}
</x-cell>
<x-cell label="职业">
{{cellData.rowData.occupation}}
</x-cell>
<x-cell label="操作" fixed="right">
<x-button text="编辑"></x-button>
<x-button text="操作"></x-button>
</x-cell>
<actions>
<button text="删除"></button>
</actions>
</x-table>
</page>

export default XPage({
data: {
tableKey: new Date().getTime(),
tableData: [
{
date: '2016-05-03',
name: '王小虎',
province: '上海',
city: '普陀区',
address: '上海市普陀区金沙江路 1518 弄',
zip: 200333,
education: '本科',
occupation: '前端工程师',
},
{
date: '2016-05-02',
name: '王小虎',
province: '上海',
city: '普陀区',
address: '上海市普陀区金沙江路 1518 弄',
zip: 200333,
education: '本科',
occupation: '前端工程师',
},
{
date: '2016-05-04',
name: '王小虎',
province: '上海',
city: '普陀区',
address: '上海市普陀区金沙江路 1518 弄',
zip: 200333,
education: '本科',
occupation: '前端工程师',
},
{
date: '2016-05-01',
name: '王小虎',
province: '上海',
city: '普陀区',
address: '上海市普陀区金沙江路 1518 弄',
zip: 200333,
education: '本科',
occupation: '前端工程师',
},
{
date: '2016-05-08',
name: '王小虎',
province: '上海',
city: '普陀区',
address: '上海市普陀区金沙江路 1518 弄',
zip: 200333,
education: '本科',
occupation: '前端工程师',
},
{
date: '2016-05-06',
name: '王小虎',
province: '上海',
city: '普陀区',
address: '上海市普陀区金沙江路 1518 弄',
zip: 200333,
education: '本科',
occupation: '前端工程师',
},
{
date: '2016-05-07',
name: '王小虎',
province: '上海',
city: '普陀区',
address: '上海市普陀区金沙江路 1518 弄',
zip: 200333,
education: '本科',
occupation: '前端工程师',
},
{
date: '2016-05-03',
name: '王小虎',
province: '上海',
city: '普陀区',
address: '上海市普陀区金沙江路 1518 弄',
zip: 200333,
education: '本科',
occupation: '前端工程师',
},
{
date: '2016-05-02',
name: '王小虎',
province: '上海',
city: '普陀区',
address: '上海市普陀区金沙江路 1518 弄',
zip: 200333,
education: '本科',
occupation: '前端工程师',
},
{
date: '2016-05-04',
name: '王小虎',
province: '上海',
city: '普陀区',
address: '上海市普陀区金沙江路 1518 弄',
zip: 200333,
education: '本科',
occupation: '前端工程师',
},
{
date: '2016-05-01',
name: '王小虎',
province: '上海',
city: '普陀区',
address: '上海市普陀区金沙江路 1518 弄',
zip: 200333,
education: '本科',
occupation: '前端工程师',
},
{
date: '2016-05-08',
name: '王小虎',
province: '上海',
city: '普陀区',
address: '上海市普陀区金沙江路 1518 弄',
zip: 200333,
education: '本科',
occupation: '前端工程师',
},
{
date: '2016-05-06',
name: '王小虎',
province: '上海',
city: '普陀区',
address: '上海市普陀区金沙江路 1518 弄',
zip: 200333,
education: '本科',
occupation: '前端工程师',
},
{
date: '2016-05-07',
name: '王小虎',
province: '上海',
city: '普陀区',
address: '上海市普陀区金沙江路 1518 弄',
zip: 200333,
education: '本科',
occupation: '前端工程师',
},
],
},

tableRendered() {
this.getComponent('table').select([1, 2, 4]);
this.getComponent('table').select({
rowNum: 3,
attrs: {
disabled: true,
},
});
},

beforeRequest(params) {
return params;
},

refresh() {
this.tableKey = new Date().getTime();
},
});


表格行上下移

PCPhonePad

<page class="demo-box">
<form type="search" confirm-button bindconfirm="search">
<item label="姓名" node="input" name="name"></item>
<item label="学历" node="select" data="{{educations}}" name="education"></item>
</form>
<table
x="table"
height="300px"
type="super"
pageable="{{ pageSize: 20 }}"
ajax="{{ajax}}"
selectable="{{multiple: true,beforeRenderCheckbox}}"
>
<toolbar>
<button icon="x-icon-action-move_up" bindclick="handleMove(-1)" />
<button icon="x-icon-action-move_down" bindclick="handleMove(1)" />
</toolbar>
<cell label="No." name="rowNO" :visible="true" fixed="left">
{{cellData.rowNO}}
</cell>
<cell label="日期" name="date" :visible="false">
{{cellData.rowData.date}}
</cell>
<cell
dm-for="(column, index) in columns"
key="{{column.name}}"
name="{{column.name}}"
label="{{column.label}}"
tips="{{column.tips}}"
>
{{cellData.rowData[column.name]}}
</cell>
<cell label="详细地址" name="address" :visible="true">
{{cellData.rowData.address}}
</cell>
<cell label="邮编" name="zip" :visible="false">
{{cellData.rowData.zip}}
</cell>
<cell label="学历" name="education" :visible="false">
{{cellData.rowData.education}}
</cell>
<cell label="职业" name="occupation" :visible="false">
{{cellData.rowData.occupation}}
</cell>
<cell label="操作" fixed="right">
<button text="编辑" bindclick="handleEdit(cellData.rowData.name)"></button>
<button text="操作" bindclick="handleOper(cellData.rowData.name)"></button>
</cell>
</table>
</page>

function fetchMockColumns() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve([
{
label: '姓名',
name: 'name',
tips: '姓名',
},
{
label: '省/直辖市',
name: 'province',
tips: '省/直辖市',
},
{
label: '市区',
name: 'city',
tips: '市区',
},
]);
}, 80);
});
}

export default XPage({
data: {
ajax: {
url: '//testapi-nodedmallos.dmall.com/cabinx/pcapi/table/data',
},
educations: [],
wareType: 1,
columns: [],
},

show() {
this.init();
},

init() {
this.setData({
educations: [
{ label: '全部', value: '' },
{ label: '大专', value: '大专' },
{ label: '本科', value: '本科' },
],
});

fetchMockColumns().then((res) => {
this.setData({
columns: res,
});
});
},

search(value) {
const table = this.getComponent('table');

table.query({ params: value });
},

handleEdit(name) {
CabinX.alert({
title: '编辑',
text: `${name}Edit`,
});
},

handleOper(name) {
CabinX.alert({
title: '操作',
text: `${name}Oper`,
});
},

handleMove(offset) {
const table = this.getComponent('table');
const selected = table.getData().selected || [];
const hasSelected = !!selected.length;

if (hasSelected) {
table.moveRows(selected, offset);
}
},
beforeRenderCheckbox({rowData, rowIndent, rowIndex}) {
if ([1,3,4].includes(rowIndex)){
return {
disabled: true
}
}
return true
},
});


本地分页

PCPhonePad

<page>
<table data="{{tableData}}" height="auto" pageable="{{pageSize:10}}">
<x-cell label="日期">
{{cellData.rowData.date}}
</x-cell>
<x-cell label="姓名">
{{cellData.rowData.name}}
</x-cell>
<x-cell label="地址">
{{cellData.rowData.address}}
</x-cell>
</table>
</page>

export default XPage({
data: {
tableData: null
},
show(){
let self = this;

setTimeout(()=>{
self.setData({
tableData:tableData
})
},2000)
}
});


let tableData = [{
date: '2016-05-02',
name: '王小虎',
address: '上海市普陀区金沙江路 1518 弄'
}, {
date: '2016-05-04',
name: '王小虎',
address: '上海市普陀区金沙江路 1517 弄'
}, {
date: '2016-05-01',
name: '王小虎',
address: '上海市普陀区金沙江路 1519 弄'
}, {
date: '2016-05-03',
name: '王小虎',
address: '上海市普陀区金沙江路 1516 弄'
},{
date: '2016-05-02',
name: '王小虎',
address: '上海市普陀区金沙江路 1518 弄'
}, {
date: '2016-05-04',
name: '王小虎',
address: '上海市普陀区金沙江路 1517 弄'
}, {
date: '2016-05-01',
name: '王小虎',
address: '上海市普陀区金沙江路 1519 弄'
}, {
date: '2016-05-03',
name: '王小虎',
address: '上海市普陀区金沙江路 1516 弄'
},{
date: '2016-05-02',
name: '王小虎',
address: '上海市普陀区金沙江路 1518 弄'
}, {
date: '2016-05-04',
name: '王小虎',
address: '上海市普陀区金沙江路 1517 弄'
}, {
date: '2016-05-01',
name: '王小虎',
address: '上海市普陀区金沙江路 1519 弄'
}, {
date: '2016-05-03',
name: '王小虎',
address: '上海市普陀区金沙江路 1516 弄'
},{
date: '2016-05-02',
name: '王小虎',
address: '上海市普陀区金沙江路 1518 弄'
}, {
date: '2016-05-04',
name: '王小虎',
address: '上海市普陀区金沙江路 1517 弄'
}, {
date: '2016-05-01',
name: '王小虎',
address: '上海市普陀区金沙江路 1519 弄'
}, {
date: '2016-05-03',
name: '王小虎',
address: '上海市普陀区金沙江路 1516 弄'
},{
date: '2016-05-02',
name: '王小虎',
address: '上海市普陀区金沙江路 1518 弄'
}, {
date: '2016-05-04',
name: '王小虎',
address: '上海市普陀区金沙江路 1517 弄'
}, {
date: '2016-05-01',
name: '王小虎',
address: '上海市普陀区金沙江路 1519 弄'
}, {
date: '2016-05-03',
name: '王小虎',
address: '上海市普陀区金沙江路 1516 弄'
},{
date: '2016-05-02',
name: '王小虎',
address: '上海市普陀区金沙江路 1518 弄'
}, {
date: '2016-05-04',
name: '王小虎',
address: '上海市普陀区金沙江路 1517 弄'
}, {
date: '2016-05-01',
name: '王小虎',
address: '上海市普陀区金沙江路 1519 弄'
}, {
date: '2016-05-03',
name: '王小虎',
address: '上海市普陀区金沙江路 1516 弄'
},{
date: '2016-05-02',
name: '王小虎',
address: '上海市普陀区金沙江路 1518 弄'
}, {
date: '2016-05-04',
name: '王小虎',
address: '上海市普陀区金沙江路 1517 弄'
}, {
date: '2016-05-01',
name: '王小虎',
address: '上海市普陀区金沙江路 1519 弄'
}, {
date: '2016-05-03',
name: '王小虎',
address: '上海市普陀区金沙江路 1516 弄'
},{
date: '2016-05-02',
name: '王小虎',
address: '上海市普陀区金沙江路 1518 弄'
}, {
date: '2016-05-04',
name: '王小虎',
address: '上海市普陀区金沙江路 1517 弄'
}, {
date: '2016-05-01',
name: '王小虎',
address: '上海市普陀区金沙江路 1519 弄'
}, {
date: '2016-05-03',
name: '王小虎',
address: '上海市普陀区金沙江路 1516 弄'
},{
date: '2016-05-02',
name: '王小虎',
address: '上海市普陀区金沙江路 1518 弄'
}, {
date: '2016-05-04',
name: '王小虎',
address: '上海市普陀区金沙江路 1517 弄'
}, {
date: '2016-05-01',
name: '王小虎',
address: '上海市普陀区金沙江路 1519 弄'
}, {
date: '2016-05-03',
name: '王小虎',
address: '上海市普陀区金沙江路 1516 弄'
},{
date: '2016-05-02',
name: '王小虎',
address: '上海市普陀区金沙江路 1518 弄'
}, {
date: '2016-05-04',
name: '王小虎',
address: '上海市普陀区金沙江路 1517 弄'
}, {
date: '2016-05-01',
name: '王小虎',
address: '上海市普陀区金沙江路 1519 弄'
}, {
date: '2016-05-03',
name: '王小虎',
address: '上海市普陀区金沙江路 1516 弄'
},{
date: '2016-05-02',
name: '王小虎',
address: '上海市普陀区金沙江路 1518 弄'
}, {
date: '2016-05-04',
name: '王小虎',
address: '上海市普陀区金沙江路 1517 弄'
}, {
date: '2016-05-01',
name: '王小虎',
address: '上海市普陀区金沙江路 1519 弄'
}, {
date: '2016-05-03',
name: '王小虎',
address: '上海市普陀区金沙江路 1516 弄'
},{
date: '2016-05-02',
name: '王小虎',
address: '上海市普陀区金沙江路 1518 弄'
}, {
date: '2016-05-04',
name: '王小虎',
address: '上海市普陀区金沙江路 1517 弄'
}, {
date: '2016-05-01',
name: '王小虎',
address: '上海市普陀区金沙江路 1519 弄'
}, {
date: '2016-05-03',
name: '王小虎',
address: '上海市普陀区金沙江路 1516 弄'
},{
date: '2016-05-02',
name: '王小虎',
address: '上海市普陀区金沙江路 1518 弄'
}, {
date: '2016-05-04',
name: '王小虎',
address: '上海市普陀区金沙江路 1517 弄'
}, {
date: '2016-05-01',
name: '王小虎',
address: '上海市普陀区金沙江路 1519 弄'
}, {
date: '2016-05-03',
name: '王小虎',
address: '上海市普陀区金沙江路 1516 弄'
}]


异步数据渲染

注意:许多使用过cabin2.0的小伙伴都清楚,一个有分页功能的表格,是通过表格组件,分页组件实现交互,请求数据的逻辑和分页的逻辑由研发自己编写实现的。

在cabinx中,我们简化了这个的实现复杂度,你只需提供请求的相关参数(如url,业务参数),和了解这个插件所需要的数据格式。

ajax类型为对象

PCPhonePad
<page class="demo-box">
<form type="search" confirm-button bindconfirm="search">
<item label="姓名" node="input" name="name"></item>
<item label="学历" node="select" data="{{educations}}" name="education"></item>
</form>
<table
x="table"
height="300px"
pageable="{{ pageSize: 10 }}"
ajax="{{ajax}}"
beforeRequest="{{beforeRequest2}}"
beforeRender="{{beforeRender}}"
bind-rendered="handleRendered"
>
<tag slot="caption" text="DBA人数:{{dbaCount}}"></tag>
<cell label="No." fixed="left">
{{cellData.rowNO}}
</cell>
<cell label="日期">
{{cellData.rowData.date}}
</cell>
<cell label="姓名">
{{cellData.rowData.name}}
</cell>
<cell label="省/直辖市">
{{cellData.rowData.province}}
</cell>
<cell label="市区">
{{cellData.rowData.city}}
</cell>
<cell label="详细地址">
{{cellData.rowData.address}}
</cell>
<cell label="邮编">
{{cellData.rowData.zip}}
</cell>
<cell label="学历">
{{cellData.rowData.education}}
</cell>
<cell label="职业">
{{cellData.rowData.occupation}}
</cell>
<cell label="操作" fixed="right">
<button text="编辑" bindclick="handleEdit(cellData.rowData.name)"></button>
<button text="操作" bindclick="handleOper(cellData.rowData.name)"></button>
</cell>
</table>
</page>

export default XPage({
data: {
ajax: {
url: '//testapi-nodedmallos.dmall.com/cabinx/pcapi/table/data',
},
educations: [],
dbaCount: 0,
},

show() {
this.init();
},

init() {
this.setData({
educations: [
{ label: '全部', value: '' }, { label: '大专', value: '大专' }, { label: '本科', value: '本科' }
],
});
},

search(value) {
const table = this.getComponent('table');

table.query({ params: value });
},

handleEdit(name) {
CabinX.alert({
title: '编辑',
text: `${name}Edit`,
});
},

handleOper(name) {
CabinX.alert({
title: '操作',
text: `${name}Oper`
});
},

/**
* 接口请求前,自定义入参
* @param {Object} args
* @param {Array} sorts 表格列排序字段
*/
beforeRequest(params, sorts) {
const newParams = params;
const surname = '李';

// 李氏三亚人 demo
if ((params.name || '').indexOf(surname) !== -1) {
Object.assign(newParams, { city: '三亚市' });
}

this.setData({
tableStatus: 'loading',
});

return newParams;
},

/**
* 接口数据返回后,自定义返回数据
* @param {Object} res
* @returns
*/
beforeRender(res) {
/*姓名脱敏 */
res.data.result = res.data.result.map(item => {
const { name, ...rest } = item;
const first = name.slice(0, 1);

const finalName = name.length <= 2
? first.padEnd(name.length, '*')
: `${first}${name.slice(-1).padStart(name.length - 1, '*')}`;

return { name: finalName, ...rest };
});

return res;
},

/**
* 表格rendered (渲染完成)listener
*/
handleRendered({ data }) {
this.setData({
dbaCount: data.reduce((acc, cur) => acc + (cur.occupation === 'DBA' ? 1 : 0), 0),
});
},
beforeRequest2(data){
delete data.name;
return data;
},
});


ajax类型为Promise

PCPhonePad
<page class="demo-box">
<head>
<form type="search" confirm-button bindconfirm="search">
<item label="姓名" node="input" name="name"></item>
<item label="学历" node="select" data="{{educations}}" name="education"></item>
</form>
</head>
<main>
<table
x="table"
pageable
ajax="{{fetchData}}"
beforeRequest="{{beforeRequest}}"
>
<cell label="No." fixed="left">
{{cellData.rowNO}}
</cell>
<cell label="日期">
{{cellData.rowData.date}}
</cell>
<cell label="姓名">
{{cellData.rowData.name}}
</cell>
<cell label="省/直辖市">
{{cellData.rowData.province}}
</cell>
<cell label="市区">
{{cellData.rowData.city}}
</cell>
<cell label="详细地址">
{{cellData.rowData.address}}
</cell>
<cell label="邮编">
{{cellData.rowData.zip}}
</cell>
<cell label="学历">
{{cellData.rowData.education}}
</cell>
<cell label="职业">
{{cellData.rowData.occupation}}
</cell>
<cell label="操作" fixed="right">
<button text="编辑" bindclick="handleEdit(cellData.rowData.name)"></button>
<button text="操作" bindclick="handleOper(cellData.rowData.name)"></button>
</cell>
</table>
</main>
</page>

export default XPage({
props: {
ajaxIsFunc: {
type: Boolean,
default: false,
}
},

data: {
educations: [],
},

show() {
this.init();
},

init() {
this.setData({
educations: [
{ label: '全部', value: '' }, { label: '大专', value: '大专' }, { label: '本科', value: '本科' }
],
});
},

search(value) {
const table = this.getComponent('table');

table.query({ params: value });
},

handleEdit(name) {
CabinX.alert({
title: '编辑',
text: `${name}Edit`,
});
},

handleOper(name) {
CabinX.alert({
title: '操作',
text: `${name}Oper`
});
},

/**
* 接口请求前,自定义入参
* @param {Object} args
* @param {Array} sorts 表格列排序字段
*/
beforeRequest(params, sorts) {
let newParams = params;

// 编辑参数
newParams.custom = '大幅度发';

return newParams;
},

fetchData(params) {
return CabinX.ajax({ withCredentials: true }).get({
url: '//testapi-nodedmallos.dmall.com/cabinx/pcapi/table/data',
params,
});
},
});


表格自定义列

信息

自定义列展示需要依赖 cell 标签上的 visible 和 name 属性, 且visible 属性必须是 布尔值, 本地自定义存储

PCPhonePad

<page class="demo-box">
<form type="search" confirm-button bindconfirm="search">
<item label="姓名" node="input" name="name"></item>
<item label="学历" node="select" data="{{educations}}" name="education"></item>
</form>
<table
x="table"
height="500px"
pageable="{{ pageSize: 10 }}"
ajax="{{ajax}}"
selectable="{{selectable}}"
@column-changed="tableFilterChange"
:columnSettable="columnSettable"
>
<radio slot="caption" class="fix-radio-button" x="radio" value="{{wareType}}" data="{{[{label:'推荐商品',value:1},{label:'更多商品',value:2}]}}" display-type="button" bindchanged="handleWareTypeChage"></radio>
<toolbar
data="{[
{ name: 'export' },
{ name: 'print' },
{ name: 'download'},
]}"
bindtool-click="handleToolClick"
>
<button text="打印跨页选择结果" bindclick="showMultipageSelected" />
<button icon="x-icon-action-move_up" bindclick="handleMove(-1)" />
<button icon="x-icon-action-move_down" bindclick="handleMove(1)" />
</toolbar>
<cell label="No." name="rowNO" :visible="true" fixed="left">
{{cellData.rowNO}}
</cell>
<cell label="日期" name="date" :visible="false">
{{cellData.rowData.date}}
</cell>
<cell
dm-for="(column, index) in columns"
key="{{column.name}}"
name="{{column.name}}"
label="{{column.label}}"
tips="{{column.tips}}"
>
{{cellData.rowData[column.name]}}
</cell>
<cell label="详细地址" name="address" :visible="true">
{{cellData.rowData.address}}
</cell>
<cell label="邮编" name="zip" :visible="false">
{{cellData.rowData.zip}}
</cell>
<cell label="学历" name="education" :visible="false">
{{cellData.rowData.education}}
</cell>
<cell label="职业" name="occupation" :visible="false">
{{cellData.rowData.occupation}}
</cell>
<cell label="操作" fixed="right">
<button text="编辑" bindclick="handleEdit(cellData.rowData.name)"></button>
<button text="操作" bindclick="handleOper(cellData.rowData.name)"></button>
</cell>
</table>
</page>

function fetchMockColumns() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve([
{
label: '姓名',
name: 'name',
tips: '姓名',
},
{
label: '省/直辖市',
name: 'province',
tips: '省/直辖市',
},
{
label: '市区',
name: 'city',
tips: '市区',
},
]);
}, 80);
});
}

export default XPage({
data: {
ajax: {
url: '//testapi-nodedmallos.dmall.com/cabinx/pcapi/table/data',
},
educations: [],
wareType: 1,
columnSettable: {
draggable: true, // 可以拖动
persist: true,
tips: '自定义列',
},
columns: [],
selectable: {
multiple: true,
multipage: true,
valueKey: 'name',
labelKey: 'name',
initialMultipageSelected: [
{ value: '范杰', label: '范杰' },
{ value: '邹涛', label: '邹涛' },
],
},
},

show() {
this.init();
},

init() {
this.setData({
educations: [
{ label: '全部', value: '' },
{ label: '大专', value: '大专' },
{ label: '本科', value: '本科' },
],
});

fetchMockColumns().then((res) => {
this.setData({
columns: res,
});
});
},

search(value) {
const table = this.getComponent('table');

table.query({ params: value });
},

handleEdit(name) {
CabinX.alert({
title: '编辑',
text: `${name}Edit`,
});
},

handleOper(name) {
CabinX.alert({
title: '操作',
text: `${name}Oper`,
});
},

handleToolClick(tool) {
const { name } = tool;

console.log('tool ', tool);
},

// 表格列的变动后会触发这个方法(拖动、展示、隐藏、pin)
tableFilterChange(data = []) {
const fields = [];

data.forEach((item) => {
// 表格cell 上设置了名称 并且 visible 是ture 就代表是显示
if (item.visible !== false && item.name) {
fields.push(item.name);
}
});

console.log('tableFilterChange: ', fields);

return fields;
},

handleWareTypeChage(wareType) {
this.setData({
wareType,
});
console.log('handleWareTypeChage:', this.data.wareType);
},

handleMove(offset) {
const table = this.getComponent('table');
const [rowIndex] = table.getData().selected || [];

if (rowIndex) {
table.moveRow(+rowIndex, +rowIndex + offset);
}
},

showMultipageSelected() {
const selected = this.getComponent('table').getMultipageSelected();

console.log('multipageSelected', selected);
}
});


信息

自定义列可以通过columnSettable.initialColumns初始,适应于后端保存自定义列配置。

PCPhonePad

<page class="demo-box">
<form type="search" confirm-button bindconfirm="search">
<item label="姓名" node="input" name="name"></item>
<item label="学历" node="select" data="{{educations}}" name="education"></item>
</form>
<table
x="table"
height="300px"
title="自定义表格列"
pageable="{{ pageSize: 10 }}"
ajax="{{ajax}}"
selectable
@column-changed="tableFilterChange"
:columnSettable="columnSettable"
>
<cell label="No." name="rowNO" fixed="left">
{{cellData.rowNO}}
</cell>
<cell label="日期" name="date">
{{cellData.rowData.date}}
</cell>
<cell label="姓名" name="name">
{{cellData.rowData.name}}
</cell>
<cell label="省/直辖市" name="province">
{{cellData.rowData.province}}
</cell>
<cell label="市区" name="city">
{{cellData.rowData.city}}
</cell>
<cell label="详细地址" name="address">
{{cellData.rowData.address}}
</cell>
<cell label="邮编" name="zip">
{{cellData.rowData.zip}}
</cell>
<cell label="学历" name="education">
{{cellData.rowData.education}}
</cell>
<cell label="职业" name="occupation">
{{cellData.rowData.occupation}}
</cell>
<cell label="操作" fixed="right">
<button text="编辑" bindclick="handleEdit(cellData.rowData.name)"></button>
<button text="操作" bindclick="handleOper(cellData.rowData.name)"></button>
</cell>
</table>
</page>


function fetchMockColumns() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve([
{ name: 'name', visible: true, fixed: 'content' },
{ name: 'date', visible: true, fixed: 'content' },
{ name: 'province', visible: false, fixed: 'content' },
{ name: 'city', visible: false, fixed: 'content' },
{ name: 'address', visible: false, fixed: 'content' },
{ name: 'zip', visible: true, fixed: 'content' },
{ name: 'education', visible: true, fixed: 'content' },
{ name: 'occupation', visible: true, fixed: 'content' },
]);
}, 100);
});
}

export default XPage({
data: {
ajax: {
url: '//testapi-nodedmallos.dmall.com/cabinx/pcapi/table/data',
},
educations: [],
wareType: 1,
columnSettable: {
draggable: true, // 可以拖动
persist: false,
tips: '自定义列',
initialColumns: [],
},
},

show() {
this.init();
},

init() {
this.setData({
educations: [
{ label: '全部', value: '' }, { label: '大专', value: '大专' }, { label: '本科', value: '本科' }
],
});

this.initTaleColumns();
},

initTaleColumns() {
// 可通过ajax调用后端接口初始化列的数据
fetchMockColumns().then(columns => {
this.setData({
'columnSettable.initialColumns': columns,
});
});
},

search(value) {
const table = this.getComponent('table');

table.query({ params: value });
},

handleEdit(name) {
CabinX.alert({
title: '编辑',
text: `${name}Edit`,
});
},

handleOper(name) {
CabinX.alert({
title: '操作',
text: `${name}Oper`
});
},

handleToolClick(tool) {
const { name } = tool;

console.log('tool ', tool);
},

// 表格列的变动后会触发这个方法(拖动、展示、隐藏、pin)
tableFilterChange(data = []) {
const fields = [];

data.forEach((item) => {
// 表格cell 上设置了名称 并且 visible 是ture 就代表是显示
if (item.visible !== false && item.name) {
fields.push(item.name)
}
})


console.log('tableFilterChange: ', fields)

return fields
},
handleWareTypeChage(wareType) {
this.setData({
wareType
});
console.log('handleWareTypeChage:', this.data.wareType);

},
handleMove(offset) {
const table = this.getComponent('table');
const [rowIndex] = table.getData().selected || [];

if (rowIndex) {
table.moveRow(+rowIndex, +rowIndex + offset);
}
},
});


表格下钻(树形数据)

当rowData中含children属性时, 将按照树进行渲染。如果ajax返回的行数据不包含children属性可以通过beforeRender方法增加。

PCPhonePad
<page>
<table
height="auto"
bordered
summary="{{summary}}"
ajax="//testapi-nodedmallos.dmall.com/cabinx/pcapi/table/children"
beforeRender="{{beforeRender}}"
bind-rendered="handleTableRendered"
>
<cell label="采销部类">
{{cellData.rowData.aggName}}
</cell>
<cell label="采销部类编码">
{{cellData.rowData.aggCode}}
</cell>
<cell label="库商品" name="sex">
{{cellData.rowData.zeroStockCount}}
</cell>
<cell label="畅缺商品">
{{cellData.rowData.lackStockCount}}
</cell>
<cell label="总店品项数">
{{cellData.rowData.allCount}}
</cell>
<cell label="缺货率">
{{cellData.rowData.stockoutRate}}
</cell>
<cell label="主数据" align="right">
<button text="{{String(cellData.rowData.mainDataExceptionNum)}}" type="link" />
</cell>
<cell label="门店" align="right">
<button text="{{String(cellData.rowData.storeNum)}}" type="link" />
</cell>
<cell label="供应商" align="right">
<button text="{{String(cellData.rowData.purchaseNum)}}" type="link" />
</cell>
</table>
</page>

export default XPage({
data: {
sex: [{value: '男', label: '男'}, {value: '女', label: '女'}],
summary: {
data: []
}
},

beforeRender(res) {
const traverse = (list) => {
return list.map(item => {
const {childList, ...rest} = item;

return {
...rest,
children: childList ? traverse(childList) : null
};
});
}

res.data.result = traverse(res.data.result);

return res;
},

handleTableRendered({data}) {
if (!data || !data.length) {
return;
}

const fields = [
['aggCode', ''],
['zeroStockCount', 0],
['lackStockCount', 0],
['allCount', 0],
['stockoutRate', ''],
['mainDataExceptionNum', 0],
['storeNum', 0],
['purchaseNum', 0]
];
let label = '总计:';
const summaryData = data.reduce((acc, cur) => {
const {aggParentCode} = cur;
if (aggParentCode != null) {
return {label, value: acc};
}

fields.forEach((field, index) => {
const [key, value] = field;

if (typeof value === 'number') {
let val = acc[ index ] ? ( acc[ index ].value!==undefined ? acc[ index ].value : acc[ index ] ) : 0
acc[ index ] = {
label,
value: val + ( cur[ key ] || 0 )
}
}
});

return acc;
}, []);
setTimeout(()=>{
this.setData({
'summary.data': summaryData
});
},5000)
}
});


表格下钻(数据异步加载)

通过tree-props属性设置加载下钻数据的函数和是否包含下钻数据的属性名

PCPhonePad
<page>
<table
x="table"
height="auto"
bordered
row-key="aggCode"
tree-props="{{ hasChildrenKey: 'hasChild', load: loadChildRows }}"
summary="{{summary}}"
ajax="{{fetchData}}"
beforeRender="{{beforeRender}}"
bind-rendered="handleTableRendered"
>
<cell label="采销部类">
{{cellData.rowData.aggName}}
</cell>
<cell label="采销部类编码">
{{cellData.rowData.aggCode}}
</cell>
<cell label="库商品" name="sex">
{{cellData.rowData.zeroStockCount}}
</cell>
<cell label="畅缺商品">
{{cellData.rowData.lackStockCount}}
</cell>
<cell label="总店品项数">
{{cellData.rowData.allCount}}
</cell>
<cell label="缺货率">
{{cellData.rowData.stockoutRate}}
</cell>
<cell label="主数据" align="right">
<button text="{{String(cellData.rowData.mainDataExceptionNum)}}" type="link" />
</cell>
<cell label="门店" align="right">
<button text="{{String(cellData.rowData.storeNum)}}" type="link" />
</cell>
<cell label="供应商" align="right">
<button text="{{String(cellData.rowData.purchaseNum)}}" type="link" />
</cell>
</table>
</page>

function fetchTreeTableData(params = {}) {
return CabinX.ajax({
url: '//testapi-nodedmallos.dmall.com/cabinx/pcapi/table/children/lazy',
method: 'get',
params,
});
}

function traverse(list) {
return list.map(item => {
const { leaf, ...rest } = item;

return {
...rest,
hasChild: leaf === false,
};
});
}

export default XPage({
data: {
sex: [{ value: '男', label: '男' }, { value: '女', label: '女' }],
summary: {
data: []
}
},

beforeRender(res) {
return res;
},

handleTableRendered({ data }) {
if (!data || !data.length) {
return;
}

const fields = [
['aggCode', ''],
['zeroStockCount', 0],
['lackStockCount', 0],
['allCount', 0],
['stockoutRate', ''],
['mainDataExceptionNum', 0],
['storeNum', 0],
['purchaseNum', 0]
];
let label = '总计:';
const summaryData = data.reduce((acc, cur) => {
const { aggParentCode } = cur;
if (aggParentCode != null) {
return { label, value: acc };
}

fields.forEach((field, index) => {
const [key, value] = field;

if (typeof value === 'number') {
let val = acc[index] ? (acc[index].value !== undefined ? acc[index].value : acc[index]) : 0
acc[index] = {
label,
value: val + (cur[key] || 0)
}
}
});

return acc;
}, []);
setTimeout(() => {
this.setData({
'summary.data': summaryData
});
}, 5000);

this.getComponent('table').expandRow('AH01');
},

fetchData(params) {
return fetchTreeTableData(params);
},

loadChildRows(rowData, callback) {
const { aggCode: parentId } = rowData || {};

return fetchTreeTableData({
parentId,
}).then(({ data }) => {
callback(data.result);
});
}
});


行列合并

通过设置cell的属性span定义行列合并,当值为字符串'same'时,跨行合并值相同的单元格;为函数时自定义合并规则

PCPhonePad
<page class="demo-box">
<!--dm-if=false 改元素将不会创建-->
<module title="表格行列合并" foldable dm-if="false">
<actions>
<button text="详情" icon="x-icon-action-edit-log" no-bordered status="primary"></button>
</actions>
<main>
测试一下
</main>
</module>
<table
x="table"
height="auto"
data="{{tableData}}"
span="{{calcSpan}}"
>
<cell label="姓名1" fixed="left" width="150px" name="name" align="center" sortable sublabel="我的姓名" span="same">
<actions>
<button text="功能" />
</actions>
{{cellData.rowData.name}}
</cell>
<cell label="性别" name="sex">
<cell label="男性">
<cell label="男性1" width="100px" name="sex" span="same">
<cell label="男性1.1" width="100px" name="sex" span="same">
{{cellData.rowData.sex}}
</cell>
</cell>
<cell label="男性2" width="100px" name="sex">
{{cellData.rowData.sex}}
</cell>
<cell label="男性3" width="100px" name="sex" sortable>
{{cellData.rowData.sex}}
</cell>
</cell>
<cell label="女性" width="120px">
{{cellData.rowData.sex}}
</cell>
<cell label="未知" width="120px" align="center">
{{cellData.rowData.sex}}
</cell>
</cell>
<cell label="电话号码" name="phone" width="150px" align="right" sortable>
{{cellData.rowData.phone}}
</cell>
<cell label="出生时辰">
<cell label="出生日期" name="birthDate" width="150px" sortable>
{{cellData.rowData.birthDate}}
</cell>
<cell label="出生时间" name="birthTime" width="150px" sortable>
{{cellData.rowData.birthTime}}
</cell>
</cell>
<cell label="出生地址2" name="birthAddress" width="150px" span="same">
{{cellData.rowData.birthAddress}}
</cell>
<cell label="操作" name="operation" width="200px" fixed>
<button status="primary" no-bordered text="编辑" @click="handleClick"></button>
<button status="primary" no-bordered text="删除" danger @click="handleClick('del', cellData.rowData)"></button>
<button status="primary" no-bordered text="修改门店" @click="handleClick('del', cellData.rowData)"></button>
<button status="primary" no-bordered text="删除门店" @click="handleClick('del', cellData.rowData)"></button>
</cell>
</table>
</page>

function moment(value) {
const timestamp = Date.parse(value);
const isValid = !isNaN(timestamp);
const date = new Date(timestamp);

return {
toDate() {
return date;
},

format(template) {
if (!isValid) {
return String(value);
}

const units = {
'YYYY': () => date.getFullYear(),
'MM': () => date.getMonth() + 1,
'DD': () => date.getDate(),
'HH': () => date.getHours(),
'mm': () => date.getMinutes(),
'ss': () => date.getSeconds(),
}

return template.replace(/\b(\w+)/g, ($0, $1) => {
const unit = units[$1];
if (!unit) {
return '';
}

const ret = String(unit());

return ret.padStart($1.length, '0');
});
},

isValid,
};
}

export default XPage({
data: {
sex: [{ value: '男', label: '男' }, { value: '女', label: '女' }],
tableData: [{
id: '000',
name: '王大虎',
sex: '男',
birthAddress: '地址1',
phone: 13688339329,
birthDate: moment('1990-2-1').toDate(),
birthTime: moment('1990-1-1 12:13:00').toDate()
}, {
id: '001',
name: '王大虎',
sex: '男',
birthAddress: '地址1',
phone: 13688339329,
birthDate: moment('1990-1-1').toDate(),
birthTime: moment('1990-1-1 12:13:00').toDate()
}, {
id: '002',
name: '王二虎',
sex: '男',
birthAddress: '地址2',
phone: 13688339329,

birthDate: moment('1990-1-1').toDate(),
birthTime: moment('1999-1-1 01:13:00').toDate()
}, {
id: '003',
name: '王三虎',
sex: '男',
birthAddress: '地址3',
phone: 13688339329,

birthDate: moment('1980-1-1').toDate(),
birthTime: moment('1980-1-1 18:13:00').toDate()
}, {
id: '004',
name: '王四虎',
sex: '男',
birthAddress: '地址4',
phone: 13688339329,

birthDate: moment('1994-1-1').toDate(),
birthTime: moment('1994-1-1 20:13:00').toDate()
},
{
id: '005',
name: '王四虎',
sex: '男',
birthAddress: '地址4',
phone: 13688339329,
birthDate: moment('1994-1-1').toDate(),
birthTime: moment('1994-1-1 20:13:00').toDate()
}].map(({ birthDate, birthTime, ...rest }) => {
return {
...rest,
birthDate: moment(birthDate).format('YYYY-MM-DD'),
birthTime: moment(birthTime).format('HH:mm:ss'),
};
}),
submitData: {},
},
handleClick() {

},
calcSpan({ rowIndex, columnIndex, row, column }) {
if (rowIndex % 2 === 0) {
if (columnIndex === 3) {
return { rowspan: 1, colspan: 2 };
} else if (columnIndex === 4) {
return { rowspan: 0, colspan: 0 };
}
}
},
});


表格排序

通过设置cell的属性sortable和name开启列排序功能,可以通过initialSorts属性设置默认排序信息,ajax获取数据时,默认通过字段sort带上排序信息,调用后端的接口返回已排序的数据。如需自定义该字段的key和value,可在beforeRequest中定义排序字段信息。针对表格的数据通过data属性绑定的场景,可以前端排序,通过监听sort事件获取排序信息,按照业务场景自行排序。

后端排序

PCPhonePad

<page class="demo-box">
<head>
<form type="search" confirm-button bindconfirm="search">
<item label="姓名111" node="input" name="name"></item>
<item label="学历222" node="select" data="{{educations}}" name="education"></item>
</form>
</head>
<main>
<table
x="table"
sortMultiple
ajax="{{ajax}}"
pageable="{{ pageSize: 10 }}"
bindsort="handleTableSorted"
initialSorts="{{initialSorts}}"
beforeRequest="{{beforeTableRequest}}"
>
<cell label="No." name="rowNO" fixed="left">
{{cellData.rowNO}}
</cell>
<cell label="日期" name="date" sortable>
{{cellData.rowData.date}}
</cell>
<cell label="姓名" name="name" sortable>
{{cellData.rowData.name}}
</cell>
<cell label="省/直辖市" name="province">
{{cellData.rowData.province}}
</cell>
<cell label="市区" name="city">
{{cellData.rowData.city}}
</cell>
<cell label="详细地址" name="address">
{{cellData.rowData.address}}
</cell>
<cell label="邮编" name="zip">
{{cellData.rowData.zip}}
</cell>
<cell label="学历" name="education">
{{cellData.rowData.education}}
</cell>
<cell label="职业" name="occupation">
{{cellData.rowData.occupation}}
</cell>
<cell label="操作" fixed="right">
<button text="编辑" bindclick="handleEdit(cellData.rowData.name)"></button>
<button text="操作" bindclick="handleOper(cellData.rowData.name)"></button>
</cell>
</table>
</main>
</module>
</page>

export default XPage({
data: {
ajax: {
url: '//testapi-nodedmallos.dmall.com/cabinx/pcapi/table/data',
},
educations: [],
columnSettable: {
draggable: true, // 可以拖动
persist: true,
tips: '自定义列'
},
initialSorts: [
{ name: 'name', order: 'asc' }, // order: 'desc' | 'asc',
],
},

show() {
this.init();
},

init() {
this.setData({
educations: [
{ label: '全部', value: '' }, { label: '大专', value: '大专' }, { label: '本科', value: '本科' }
],
});
},

search(value) {
const table = this.getComponent('table');

table.query({ params: value });
},

handleEdit(name) {
CabinX.alert({
title: '编辑',
text: `${name}Edit`,
});
},

handleTableSorted(sortParams) {
console.log('sortParams', sortParams);
},

beforeTableRequest(params, sortParams) {
const sortInfo = sortParams.map((item) => {
const { name, order } = item;

return `${name}|${order}`;
}).join(',');

return {
...params,
sort: sortInfo,
};
},
});


前端排序

PCPhonePad

<page>
<head>
<form type="search" confirm-button bindconfirm="search">
<item label="姓名" node="input" name="name"></item>
<item label="学历" node="select" data="{{educations}}" name="education"></item>
</form>
</head>
<main>
<table
x="table"
type="super"
pageable="{{ pageSize: 20 }}"
data="{{tableData}}"
bindsort="handleTableSort"
>
<cell label="No." name="rowNO" fixed="left">
{{cellData.rowNO}}
</cell>
<cell label="姓名" name="name">
{{cellData.rowData.name}}
</cell>
<cell label="出生日期" name="date" sortable>
{{cellData.rowData.date}}
</cell>
<cell label="省/直辖市" name="province">
{{cellData.rowData.province}}
</cell>
<cell label="市区" name="city">
{{cellData.rowData.city}}
</cell>
<cell label="详细地址" name="address">
{{cellData.rowData.address}}
</cell>
<cell label="邮编" name="zip">
{{cellData.rowData.zip}}
</cell>
<cell label="学历" name="education">
{{cellData.rowData.education}}
</cell>
<cell label="职业" name="occupation">
{{cellData.rowData.occupation}}
</cell>
<cell label="操作" fixed="right">
<button text="编辑" bindclick="handleEditRow(cellData.rowData)"></button>
<button text="删除" bindclick="handleDeleteRow(cellData.rowData, cellData.rowIndex)"></button>
</cell>
</table>
</main>
</module>
</page>

import moment from 'moment';

// 模拟业务数据获取
function fetchTableData() {
return Promise.resolve([
{
"name": "邱勇",
"date": "1981-09-24",
"province": "海外",
"city": "双鸭山市",
"zip": "774612",
"address": "双鸭山市容二非片路212号",
"education": "本科",
"occupation": "Java工程师"
},
{
"name": "江敏",
"date": "1981-07-04",
"province": "广东省",
"city": "鞍山市",
"zip": "746656",
"address": "鞍山市身置情路600号",
"education": "本科",
"occupation": "运维"
},
{
"name": "黎静",
"date": "1972-03-30",
"province": "安徽省",
"city": "梧州市",
"zip": "823444",
"address": "梧州市法白员路477号",
"education": "大专",
"occupation": "前端工程师"
},
{
"name": "邱明",
"date": "1979-04-17",
"province": "宁夏回族自治区",
"city": "果洛藏族自治州",
"zip": "881845",
"address": "果洛藏族自治州场也基路922号",
"education": "本科",
"occupation": "Java工程师"
},
{
"name": "孟平",
"date": "1993-07-25",
"province": "四川省",
"city": "中卫市",
"zip": "972238",
"address": "中卫市活之眼路558号",
"education": "本科",
"occupation": "Java工程师"
},
{
"name": "于霞",
"date": "1987-12-23",
"province": "云南省",
"city": "喀什地区",
"zip": "949132",
"address": "喀什地区布万平路313号",
"education": "本科",
"occupation": "DBA"
},
{
"name": "张杰",
"date": "1984-05-15",
"province": "湖北省",
"city": "咸阳市",
"zip": "062896",
"address": "咸阳市段派有志路970号",
"education": "本科",
"occupation": "DBA"
},
{
"name": "林静",
"date": "1989-11-10",
"province": "云南省",
"city": "新竹县",
"zip": "894937",
"address": "新竹县个市布长路317号",
"education": "本科",
"occupation": "运维"
},
{
"name": "汤强",
"date": "1976-03-19",
"province": "香港特别行政区",
"city": "舟山市",
"zip": "153750",
"address": "舟山市接下常毛路496号",
"education": "本科",
"occupation": "DBA"
},
{
"name": "唐秀英",
"date": "2009-07-08",
"province": "湖南省",
"city": "赣州市",
"zip": "328611",
"address": "赣州市完即叫路716号",
"education": "本科",
"occupation": "前端工程师"
},
{
"name": "董秀兰",
"date": "2020-10-04",
"province": "河北省",
"city": "宿州市",
"zip": "787245",
"address": "宿州市方西且路844号",
"education": "大专",
"occupation": "DBA"
},
{
"name": "汤秀兰",
"date": "1999-01-26",
"province": "海南省",
"city": "七台河市",
"zip": "693865",
"address": "七台河市走只场非路467号",
"education": "大专",
"occupation": "DBA"
},
{
"name": "廖勇",
"date": "1977-01-01",
"province": "广西壮族自治区",
"city": "泰州市",
"zip": "653814",
"address": "泰州市容林带太路570号",
"education": "研究生",
"occupation": "DBA"
},
{
"name": "蒋平",
"date": "2020-11-22",
"province": "新疆维吾尔自治区",
"city": "岳阳市",
"zip": "635217",
"address": "岳阳市第最是状路173号",
"education": "研究生",
"occupation": "DBA"
},
{
"name": "林军",
"date": "2004-07-28",
"province": "贵州省",
"city": "防城港市",
"zip": "936227",
"address": "防城港市电后五路52号",
"education": "大专",
"occupation": "DBA"
},
{
"name": "余杰",
"date": "1981-11-13",
"province": "宁夏回族自治区",
"city": "澳门半岛",
"zip": "610244",
"address": "澳门半岛展因由路602号",
"education": "大专",
"occupation": "DBA"
},
{
"name": "薛杰",
"date": "2009-11-19",
"province": "贵州省",
"city": "盘锦市",
"zip": "487452",
"address": "盘锦市义图克路624号",
"education": "本科",
"occupation": "Java工程师"
},
{
"name": "吕平",
"date": "1974-02-17",
"province": "浙江省",
"city": "晋城市",
"zip": "262025",
"address": "晋城市我算情路532号",
"education": "本科",
"occupation": "Java工程师"
},
{
"name": "郭平",
"date": "1973-01-13",
"province": "甘肃省",
"city": "日照市",
"zip": "312303",
"address": "日照市置论史路135号",
"education": "大专",
"occupation": "Java工程师"
},
{
"name": "侯娜",
"date": "2015-03-02",
"province": "重庆",
"city": "绥化市",
"zip": "843136",
"address": "绥化市效思义七路946号",
"education": "大专",
"occupation": "DBA"
}]);
}

export default XPage({
data: {
tableData: [],
educations: [],
},

show() {
this.init();
},

async init() {
const tableData = await fetchTableData();

this.setData({
educations: [
{ label: '全部', value: '' },
{ label: '大专', value: '大专' },
{ label: '本科', value: '本科' },
],
tableData,
});
},

async search(formData) {
const fullTableData = await fetchTableData();
const { name } = formData;
const newTableData = name
? fullTableData.filter(row => row.name.indexOf(name) !== -1)
: fullTableData;

this.setData({
tableData: newTableData,
});
},

handleEditRow(rowData) {
CabinX.alert({
title: '提示',
text: `开始编辑${rowData.name}的数据`,
});
},

handleDeleteRow(rowIndex, rowData) {
const { data } = this.getComponent('table').getData();

CabinX.confirm(
{
title: '提示',
text: '您确定确定删除这条数据吗?',
},
(val) => {
if (val) {
const newTableData = [...data].splice(rowIndex, 1);

this.setData({
tableData: newTableData,
});
}
}
);
},

handleTableSort([{ name, order } = {}]) {
if (!name) {
return;
}

const { data } = this.getComponent('table').getData();
const sortedTableData = [...data];

// 按照出生日期排序
sortedTableData.sort((a, b) => {
const prevBirthDate = moment(a.date);
const nextBirthDate = moment(b.date);

// 升序
if (order === 'asc') {
return prevBirthDate - nextBirthDate;
}

// 其他
return nextBirthDate - prevBirthDate;
});

this.setData({
tableData: sortedTableData,
});
}
});

表格合计

通过设置table的属性summary定义表格列合计。

PCPhonePad
<page>
<table
data="{{tableData}}"
height="auto"
summary="{{summary}}"
>
<x-cell label="序号" width="60px">
{{cellData.rowNO}}
</x-cell>
<x-cell label="姓名">
{{cellData.rowData.name}}
</x-cell>
<x-cell label="字段1">
{{cellData.rowData.field1}}
</x-cell>
<x-cell label="字段2">
{{cellData.rowData.field2}}
</x-cell>
</table>
</page>

export default XPage({
data: {
sex: [
{ value: '男', label: '男' },
{ value: '女', label: '女' },
],
summary: {
data: [],
},
tableData: [
{
id: '000',
name: '王大虎',
field1: 10,
field2: 20,
},
{
id: '001',
name: '王大虎',
field1: 10,
field2: 20,
},
{
id: '002',
name: '王二虎',
field1: 10,
field2: 20,
},
{
id: '003',
name: '王三虎',
field1: 10,
field2: 20,
},
{
id: '004',
name: '王四虎',
field1: 10,
field2: 20,
},
{
id: '005',
name: '王四虎',
field1: 10,
field2: 20,
},
],
submitData: {},
},
show() {
const { tableData } = this.data;

const { field1, field2 } = tableData.reduce(
(acc, cur) => {
const { field1, field2 } = cur;

acc.field1 += field1;
acc.field2 += field2;

return acc;
},
{ field1: 0, field2: 0 },
);

this.setData({
'summary.data': [
'',
'',
{ label: '合计1', value: field1 },
{ label: '合计2', value: field2 },
],
});
},

handleClick() {},

calcSpan({ rowIndex, columnIndex, row, column }) {
if (rowIndex % 2 === 0) {
if (columnIndex === 3) {
return { rowspan: 1, colspan: 2 };
} else if (columnIndex === 4) {
return { rowspan: 0, colspan: 0 };
}
}
},
});


表格分组小计

在接口返回行数据的基础上,计算出分组小计数据并插入到行数据中,通过span属性设置列合并规则。

PCPhonePad
<page>
<table
height="auto"
bordered
ajax="{{fetchTableData}}"
span="{{calcSpan}}"
beforeRender="{{beforeRender}}"
beforeRowRender="{{beforeRowRender}}"
bind-rendered="handleTableRendered"
>
<cell label="采销部类">
{{cellData.rowData.aggName}}
</cell>
<cell label="采销部类编码">
{{cellData.rowData.aggCode}}
</cell>
<cell label="库商品" name="sex">
{{cellData.rowData.zeroStockCount}}
</cell>
<cell label="畅缺商品">
{{cellData.rowData.lackStockCount}}
</cell>
<cell label="总店品项数">
{{cellData.rowData.allCount}}
</cell>
<cell label="缺货率">
{{cellData.rowData.stockoutRate}}
</cell>
<cell label="主数据" align="right">
<button text="{{String(cellData.rowData.mainDataExceptionNum)}}" type="link" />
</cell>
<cell label="门店" align="right">
<button text="{{String(cellData.rowData.storeNum)}}" type="link" />
</cell>
<cell label="供应商" align="right">
<button text="{{String(cellData.rowData.purchaseNum)}}" type="link" />
</cell>
</table>
</page>

export default XPage({
data: {},

/**
* 在接口返回数据基础上,计算并新增一条小计行数据
* @param {Object} res
* @returns
*/
beforeRender(res) {
const {
data: { result },
} = res;
let currentGroup;
const rows = [];

result.forEach((item, index) => {
const { groupCode, groupName } = item;
const isLast = index === result.length - 1;

rows.push(item);

if (!currentGroup) {
currentGroup = {
name: groupName,
code: groupCode,
mainDataExceptionNum: 0,
storeNum: 0,
purchaseNum: 0,
};
}

if (currentGroup.code === groupCode) {
currentGroup.mainDataExceptionNum += item.mainDataExceptionNum;
currentGroup.storeNum += item.storeNum;
currentGroup.purchaseNum += item.purchaseNum;
}

if (currentGroup.code !== groupCode || isLast) {
const subtotalRow = {
aggName: `${currentGroup.name}小计`,
isSubtotoal: true,
mainDataExceptionNum: currentGroup.mainDataExceptionNum,
storeNum: currentGroup.storeNum,
purchaseNum: currentGroup.purchaseNum,
};

// 增加小计行数据
if (isLast) {
rows.push(subtotalRow);
} else {
rows.splice(rows.length - 1, 0, subtotalRow);
}

currentGroup = {
name: groupName,
code: groupCode,
mainDataExceptionNum: item.mainDataExceptionNum,
storeNum: item.storeNum,
purchaseNum: item.purchaseNum,
};
}
});

res.data.result = rows;

return res;
},

handleTableRendered() {},

beforeRowRender(rowData) {
if (rowData.isSubtotoal) {
return {
style: { backgroundColor: '#f5f5f5' },
};
}
},

fetchTableData(params) {
return CabinX.ajax({
url: '//testapi-nodedmallos.dmall.com/cabinx/pcapi/table/children',
method: 'get',
params,
}).then((res) => {
const {
data: { result },
} = res;

const flatData = result.reduce((acc, cur) => {
const {
aggCode: groupCode,
aggName: groupName,
childList,
} = cur;
if (!childList || !childList.length) {
return acc;
}

return acc.concat(
childList.map((item) => {
return {
...item,
groupCode,
groupName,
aggName: `${groupName}${item.aggName}`,
};
}),
);
}, []);
res.data.result = flatData;

return res;
});
},

calcSpan({ rowIndex, columnIndex, row, column }) {
if (!row.isSubtotoal) {
return;
}

const fields = [
'采销部类编码',
'库商品',
'畅缺商品',
'总店品项数',
'缺货率',
];

if (column.label === '采销部类') {
return { rowspan: 1, colspan: fields.length + 1 };
}

if (fields.indexOf(column.label) !== -1) {
return { rowspan: 1, colspan: 0 };
}
},
});


SuperTable 分组小计

summary.group设置分组统计配置

PCPhonePad
<page title="Table Summary">
<table
x="table"
type="super"
title="合计&分组小计"
editable
summary="{{summary}}"
tips="合计&分组小计demo"
ajax="{{fetchData}}"
before-render="{{beforeTableRender}}"
>
<cell label="采销部类">
{{cellData.rowData.aggName}}
</cell>
<cell label="采销部类编码">
{{cellData.rowData.aggCode}}
</cell>
<cell label="库商品" name="zeroStockCount" formatter="quantity">
{{cellData.rowData.zeroStockCount}}
</cell>
<cell label="畅缺商品" name="lackStockCount">
<editor
node="input"
disabled="{{cellData.rowData.isGroupSummary}}"
value="{{cellData.rowData.lackStockCount}}"
></editor>
</cell>
<cell label="总店品项数" formatter="quantity">
{{cellData.rowData.allCount}}
</cell>
<cell label="缺货率">
{{cellData.rowData.stockoutRate}}
</cell>
<cell label="主数据" align="right">
<button text="{{(cellData.rowData.mainDataExceptionNum || 0).toString()}}" type="link" />
</cell>
<cell label="门店" align="right">
<button text="{{(cellData.rowData.storeNum || 0).toString()}}" type="link" />
</cell>
<cell label="供应商" align="right">
<button text="{{(cellData.rowData.purchaseNum || 0).toString()}}" type="link" />
</cell>
</table>
</page>

export default XPage({
data: {
summary: {
// 分组配置
group: {
key: 'groupCode', // 分组依据该字段
text: '小计',
columns: [
// 分组统计列,通过name关联数据列
{
name: 'zeroStockCount',
},
{
name: 'lackStockCount',
},
],
},
data: [
{ value: 10000, name: 'zeroStockCount', formatter: 'quantity' },
{ label: '合计', value: 20000, name: 'lackStockCount' },
],
},
},

beforeTableRender(res) {
const { totalCount, pageSize, pageCount, currentPage, result } =
res.data;

return {
data: {
records: result,
current: currentPage,
pages: pageCount,
total: totalCount,
size: pageSize,
},
};
},

async fetchData(params) {
return CabinX.ajax({
url: '//testapi-nodedmallos.dmall.com/cabinx/pcapi/table/children',
method: 'get',
params,
}).then((res) => {
const {
data: { result },
} = res;

const flatData = result.reduce((acc, cur) => {
const {
aggCode: groupCode,
aggName: groupName,
childList,
} = cur;
if (!childList || !childList.length) {
return acc;
}

return acc.concat(
childList.map((item) => ({
...item,
groupCode,
groupName,
aggName: `${groupName}${item.aggName}`,
})),
);
}, []);

res.data.result = flatData;

return res;
});
},
});


SuperTable 跨端

需要设置移动端必须的属性,如:需要指定类型为title的cell

PCPhonePad
<page title="Super table cross">
<table
x="table"
type="super"
title="跨端的super表格"
ajax="{{fetchData}}"
before-render="{{beforeTableRender}}"
bindrendered="handleTableRendered"
cell-sort="{{['allCount','aggCode']}}"
show-rownum
pullrefresh
bindrefresh="onRefresh"
>
<cell label="商品图片" name="wareImage" width="80px" type="image">
<upload
name="wareImage"
type="image"
max-length="{{1}}"
text="选择图片"
action="{{imageAction}}"
value="{{cellData.rowData.wareImage && [cellData.rowData.wareImage] || []}}"
/>
</cell>
<cell label="采销部类" type="title" name="aggName" copiable="{{valueKey: 'aggCode'}}">
{{cellData.rowData.aggName}}
</cell>
<cell label="状态" type="tag" name="tag">
<tag text="已完成" status="success"></tag>
</cell>
<cell label="采销部类编码" name="aggCode">
{{cellData.rowData.aggCode}}
</cell>
<cell label="库商品" name="zeroStockCount" formatter="quantity">
{{cellData.rowData.zeroStockCount}}
</cell>
<cell label="总店品项数" formatter="quantity" name="allCount">
{{cellData.rowData.allCount}}
</cell>
<cell label="缺货率" name="stockoutRate">
{{cellData.rowData.stockoutRate}}
</cell>
<cell label="主数据" align="right" name="mainDataExceptionNum">
<button text="{{(cellData.rowData.mainDataExceptionNum || 0).toString()}}" type="link"/>
</cell>
<cell label="门店" align="right" name="storeNum">
<button text="{{(cellData.rowData.storeNum || 0).toString()}}" type="link"/>
</cell>
<cell label="供应商" align="right" name="purchaseNum">
<button text="{{(cellData.rowData.purchaseNum || 0).toString()}}" type="link"/>
</cell>
<cell label="操作" type="control" fixed="right" name="control">
<button text="测试1"/>
<button text="测试2"/>
<button text="测试3"/>
<button text="测试4"/>
<button text="测试5"/>
</cell>
</table>
</page>

export default XPage({
data: {
imageAction: '//testgwbasics.dmall-os.com/basics/nessau/io/file/upload', // 按照业务实际上传图片的接口填写
},

beforeTableRender(res) {
const {totalCount, pageSize, pageCount, currentPage, result} =
res.data;

return {
data: {
records: result,
current: currentPage,
pages: pageCount,
total: totalCount,
size: pageSize,
},
};
},

async fetchData(params) {
return CabinX.ajax({
url: '//testapi-nodedmallos.dmall.com/cabinx/pcapi/table/children',
method: 'get',
params,
}).then((res) => {
const {
data: {result},
} = res;

const flatData = result.reduce((acc, cur) => {
const {
aggCode: groupCode,
aggName: groupName,
childList,
} = cur;
if (!childList || !childList.length) {
return acc;
}

return acc.concat(
childList.map((item) => ({
...item,
groupCode,
groupName,
aggName: `${groupName}${item.aggName}`,
})),
);
}, []);

const [firstRowData] = flatData;

firstRowData.wareImage = {
uid: '1700382728195',
url: 'https://testimage-1256468630.cos.ap-beijing.myqcloud.com/ware/0f1ee4381b584119828261b79e42b024/screenshot-20220507-092953.png',
name: 'screenshot-20220507-092953',
};
res.data.result = flatData;

return res;
});
},

handleTableRendered() {
this.getComponent('table').activateRow(1);
},
onRefresh() {
setTimeout(() => {
this.getComponent('table').stopPullRefresh();
}, 1000);
},
});


SuperTable 筛选

需要设置filterable属性, 配合cell上node属性使用可以参考item组件, 当筛选条件改变后,会触发表格的filter事件。

PCPhonePad
<page title="SuperTable Filterable">
<table x="table" type="super" ajax="{{fetchData}}" before-render="{{beforeTableRender}}" pageable="{{pageSize: 20}}"
filterable="{{data: {radioButton: '1'}, name: 'keywords', placeholder: '请输入关键字'}}" show-rownum
bindrendered="handleTableRendered" bindfilter="handlerTableFilter">
<cell label="姓名" name="name" sortable node="input">
{{cellData.rowData.name}}
</cell>
<cell label="radioButton" name="radioButton" node="radio" displayType="button"
data="{[{label:'通过', value: '1'},{label:'驳回', value: '0'},{label: '审批中', value: '2'}]}">
{{cellData.rowData.id}}
</cell>
<cell label="checkbox" name="checkbox" node="checkbox"
data="{[{label:'通过', value: '1'},{label:'驳回', value: '0'},{label: '审批中', value: '2'}]}">
{{cellData.rowData.id}}
</cell>
<cell label="select" name="select" node="select"
data="{[{label:'通过', value: '1'},{label:'驳回', value: '0'},{label: '审批中', value: '2'}]}">
{{cellData.rowData.localeName}}
</cell>
<cell label="radio" name="radio" node="radio"
data="{[{label:'通过', value: '1'},{label:'驳回', value: '0'},{label: '审批中', value: '2'}]}">
{{cellData.rowData.id}}
</cell>
<cell label="日期" name="date" sortable node="date-picker">
{{cellData.rowData.date}}
</cell>
<cell label="省/直辖市" name="province">
{{cellData.rowData.province}}
</cell>
<cell label="市区" name="city">
{{cellData.rowData.city}}
</cell>
<cell label="详细地址" name="address">
{{cellData.rowData.address}}
</cell>
<cell label="邮编" name="zip">
{{cellData.rowData.zip}}
</cell>
<cell label="学历" name="education">
{{cellData.rowData.education}}
</cell>
<cell label="职业" name="occupation">
{{cellData.rowData.occupation}}
</cell>
<cell label="操作" fixed="right">
<button text="编辑" bindclick="handleEdit(cellData.rowData.name)"></button>
<button text="操作" bindclick="handleOper(cellData.rowData.name)"></button>
</cell>
</table>
</page>

export default XPage({
data: {},

beforeTableRender(res) {
const { totalCount, pageSize, pageCount, currentPage, result } =
res.data;

return {
data: {
records: result,
current: currentPage,
pages: pageCount,
total: totalCount,
size: pageSize,
},
};
},

async fetchData(params) {
return CabinX.ajax({
url: '//testapi-nodedmallos.dmall.com/cabinx/pcapi/table/data',
method: 'get',
params,
});
},

handleTableRendered() {
this.getComponent('table').activateRow(1);
},

handlerTableFilter(filterParams) {
console.log('filterParams',filterParams);

this.getComponent('table').query({ params: filterParams });
},

handleEdit() {

},

handleOper() {

},

onRefresh() {
setTimeout(() => {
this.getComponent('table').stopPullRefresh();
}, 1000);
},
});


filterable 配置项

参数说明类型可选值默认值版本
filterable是否开启筛选Boolean/Object--falsePC/Mobile--
filterable.data筛选项数据{name,value}----PC/Mobile--
filterable.nameinput筛选项keyString----PC/Mobile--
filterable.placeholderinput筛选项placeholderString----PC/Mobile--
filterable.queryButton是否显示筛选按钮Boolean----PC/Mobile--
filterable.customAction自定义筛选按钮Array<{icon: String, click: Function}>----Mobile--

SuperTable 单元格复制

在cell上设置copiable属性,开启单元格复制功能,默认复制name属性对应的值,可以通过valueKey属性指定复制的字段。

PCPhonePad
<page title="Super table copy demo">
<table
x="table"
type="super"
ajax="{{fetchData}}"
pageable="{{pageSize: 50}}"
before-request="{{beforeRequest}}"
before-render="{{beforeTableRender}}"
bindrendered="handleTableRendered"
>
<cell label="No." fixed="left">
{{cellData.rowNO}}
</cell>
<cell label="日期">
{{cellData.rowData.date}}
</cell>
<cell label="姓名" name="name" copiable>
{{cellData.rowData.name}}
</cell>
<cell label="省/直辖市">
{{cellData.rowData.province}}
</cell>
<cell label="市区">
{{cellData.rowData.city}}
</cell>
<cell label="详细地址" copiable="{{valueKey: 'address'}}">
{{cellData.rowData.address}}
</cell>
<cell label="邮编">
{{cellData.rowData.zip}}
</cell>
<cell label="学历">
{{cellData.rowData.education}}
</cell>
<cell label="职业">
{{cellData.rowData.occupation}}
</cell>
<cell label="操作" fixed="right">
<button text="编辑" bindclick="handleEdit(cellData.rowData.name)"></button>
<button text="操作" bindclick="handleOper(cellData.rowData.name)"></button>
</cell>
</table>
</page>

export default XPage({
data: {
},

beforeRequest(params) {
const { current, size, ...rest } = params;


return {
currentPage: current,
pageSize: size,
...rest,
};
},

beforeTableRender(res) {
const {totalCount, pageSize, pageCount, currentPage, result} = res.data;

return {
data: {
records: result,
current: currentPage,
pages: pageCount,
total: totalCount,
size: pageSize,
},
};
},

async fetchData(params) {
return CabinX.ajax({ withCredentials: true }).get({
url: '//testapi-nodedmallos.dmall.com/cabinx/pcapi/table/data',
params,
});
},

handleTableRendered() {
this.getComponent('table').activateRow(1);
},
});


SuperTable 行拖动排序

设置row-draggable属性,开启行拖动排序功能,可以监听row-dragend事件,通过事件参数data属性获取排序后的数据。

PCPhonePad
<page title="Super table drag sorting">
<table
x="table"
type="super"
pageable="{{pageSize: 10}}"
row-draggable
virtual-scroll="{{false}}"
before-request="{{beforeRequest}}"
before-render="{{beforeTableRender}}"
ajax="{{fetchData}}"
bindrow-dragend="handlerRowDragend"
bindrendered="handleTableRendered"
>
<cell label="No." fixed="left">
{{cellData.rowNO}}
</cell>
<cell label="日期">
{{cellData.rowData.date}}
</cell>
<cell label="姓名" name="name">
{{cellData.rowData.name}}
</cell>
<cell label="省/直辖市">
{{cellData.rowData.province}}
</cell>
<cell label="市区">
{{cellData.rowData.city}}
</cell>
<cell label="详细地址">
{{cellData.rowData.address}}
</cell>
<cell label="邮编">
{{cellData.rowData.zip}}
</cell>
<cell label="学历">
{{cellData.rowData.education}}
</cell>
<cell label="职业">
{{cellData.rowData.occupation}}
</cell>
<cell label="操作" fixed="right">
<button text="编辑" bindclick="handleEdit(cellData.rowData.name)"></button>
<button text="操作" bindclick="handleOper(cellData.rowData.name)"></button>
</cell>
</table>
</page>

export default XPage({
data: {
},

beforeRequest(params) {
const { current, size, ...rest } = params;


return {
currentPage: current,
pageSize: size,
...rest,
};
},

beforeTableRender(res) {
const {totalCount, pageSize, pageCount, currentPage, result} = res.data;

return {
data: {
records: result,
current: currentPage,
pages: pageCount,
total: totalCount,
size: pageSize,
},
};
},

async fetchData(params) {
return CabinX.ajax({ withCredentials: true }).get({
url: '//testapi-nodedmallos.dmall.com/cabinx/pcapi/table/data',
params,
});
},

handlerRowDragend({ oldData, data }) {
console.log('row drag end', oldData, data);
}
});


Attribute

属性说明类型可选值默认值版本
ajaxhttp请求相关的参数,与data并存时,优先
使用ajax,具体配置参考 ajax配置
String/Object/(params: Object) => Promise----PC/Mobile--
data定义表格显示的数据,与ajax 并存时失效Array< Object >----PC/Mobile--
row-key行数据的keyString--------
type类型Stringnormal/supernormal----
editable是否开启编辑模式,开启后,可以使
用表格内的编辑组建,开启后组建的使用方式参考 editable
----------
filterable是否开启筛选Boolean/Object--false----
pageable是否开启 异步 分页,具体配置参考 pageableBoolean/Object--false----
summary表格列合计Object{ text: String, data: Array}--------
beforeRender该回调方法用于将接口数据转换成表格渲染数据 转换成的标准格式参考“beforeRender的返回值格式”Function--------
beforeRequest该回调方法用于修改接口的传参格式,默认格式参考“beforeRequest的入参”Function--------
not-cabinx-tag如果需要用原生标签,可以
使用这个参数,编译器将不会对 table 转成 x-table 。注意,
这个标签只在命令行编译阶段生效,而不是运行阶段,
所以,赋值对他是没有用的
------PC/Mobile--
column-settable是否开启 自定义选择列, 具体配置参考 columnSettableBoolean/Object--false----
enterselectable 开启下 回车事件Function--false----
maxBtn操作栏最大按钮数,超出...,默认3Number/String--3----
title标题String--------
cell-content-cols移动端时cell单行内容区域的列数,最多支持3列排布String1/2/31----
cell-sort移动端时每行内容区域的排序,如:["name","id","date"](为列取值用的key的排序)Array--------
show-more仅移动端且type为super时可用,当监听了row-visited事件时需要配置该属性,每行卡片才能展示更多区域。点击该区域可查看改行全部详情信息Boolean--false----
pullrefresh仅移动端且type为super时可用,下拉刷新,触发下拉刷新时会触发refresh回调函数。注意:需要用户在回调函数中手动执行stopPullRefresh()关闭下拉刷新动效Boolean--false----
show-rownum是否增加行号列,仅type为super时可用Boolean--false----
cellContentLayout设置移动端card内容部分部分方式,仅type为super时可用Stringhorizontal/verticalhorizontalMobile--
row-draggable开启行拖动排序,仅type为super时可用Boolean--falsePC--
emptyTextConfig表格空数据提示语,可以通过全局配置也可以组件单独配置Object{no_data,no_data_search}nullPC--

beforeRender的返回值格式

  第一种
{
code:'',//错误码(非必须)
data:{
result:[{},{}],//列表数据
currentPage:1,//当前的页码
pageCount:10,//总页数
totalCount:100,//总数据条数
pageSize:10//每页条数
}

}
第二种
{
data:[{},{},{}],//列表数据
pagination:{
total:100,//总数据条数
per_page:10,//每页条数
current_page:1,//当前的页码
last_page:10//总页数
}
}

beforeRequest的入参

// 参数1 Object({ currentPage: Number, pageSize: Number })
{
currentPage: 1
pageSize: 50
... //用户参数平铺
}

// 参数2 Array<{name: String, order: 'asc' | 'desc' }>
[
{ order: 'asc', name: 'personName'}
]

ajax配置

参数说明类型可选值默认值
ajax如果ajax为string时,表示请求的url
作用与 ajax:{url:'xxx.dmall.com/abc/abc.json'} 相同
String
ajax.url请求的urlString
ajax.params请求的参数Object
ajax.methodhttp methodstringget/post
ajax.contentType请求资源MIME类型
注意:由于公司禁止使用options请求,
所以可以选值请参考多点研发必知必会中的 跨域问题 章节
跨域请求时,Content-Type默认为application/json,
browser会发起预检请求(method: options), 由于安全原因公司部分接口禁止options请求,
所以预检通过不过会报403,开发过程中发现这种情况,
请检查Content-Type是否为允许的三种类型
Stringapplication/json
application/x-www-form-urlencoded
multipart/form-data
text/plain
application/json

pageable 分页器

参数说明类型可选值默认值
pageable是否开启异步分页,!!默认不会开启!!,关闭情况下,只会从服务器拉取50条数据boolean/objecttrue/false/Objectfalse
pageable.pageSize默认每页条数Number50
pageable.mode (pc端可用)展示模式Stringcomplex/simplecomplex
pageable.showSimpleCount (pc端可用)当为 mode 为 simple 时生效,显示当前页/总页数式Booleanfalse
pageable.pageSizes每页条数选项设置Number[][10, 20, 50, 100]
pageable.httpMethod (废弃)请求方式StringGET/POSTGET
pageable.httpOptions请求关信息Object
pageable.httpOptions.withCredentials是否携带cookieBooleantrue/falsetrue
pageable.httpOptions.headers请求头相关信息Object
pageable.showPageSize(pad端可用)显示每页可选展示条数下拉列表Object
pageable.httpOptions.headers.Content-Type(废弃)设置请求的content-type,
注意:由于公司禁止使用option请求,所以可以选值请参考多点研发必知必会中的 跨域问题 章节
String

editable 编辑模式

名称说明可选值默认值
shortcutType快捷键模式common/contract(更加方便的快捷键功能)common

columnSettable 列设置

参数说明类型可选值默认值
columnSettable是否开启 自定义选择列,默认不会开启!!关闭情况下,不展示表格右上角的按钮boolean/objecttrue/false/Objectfalse
columnSettable.tips点击按钮之后右侧弹出列的标题String''
columnSettable.draggable是否可以拖动Objecttrue/falsetrue
columnSettable.persist是否持久化Booleantrue/falsefalse
columnSettable.initialColumns初始列Array<{ name: String, visible: Boolean, fixed: 'left|content|right' }>

selectable 行选择器

参数说明类型可选值默认值
selectable是否开启行选择器Boolean/Objectfalse
selectable.multiple是否为复选Booleantrue/falsefalse
selectable.showCheck是否展示勾选图标,仅在multiple为false生效true/falsetrue
selectable.multipage是开启跨页选择Booleantrue/falsefalse
selectable.valueKey设置某个行数据属性,初始选中项值,跨页必填String
selectable.labelKey设置某个行数据属性,初始选中项文本,跨页必填String
selectable.initialMultipageSelected跨页选中初始值Array<{label: String, value: any}>[]
selectable.rowSelectablemultiple 为真时如果开启,允许点击行选中Booleanfalse
selectable.beforeRenderCheckbox控制多选中的checkbox是否可见(仅super table)Function-

Event

名称说明参数
rendered渲染完成回调
selectedselectable 的选择器选中后触发{ data: Array< CellData >, row: Array< ChangedRowIndex >, selected: Array< SelectedIndex > }
unselectedselectable 的选择器反选后触发{ data: Array< CellData >, row: Array< ChangedRowIndex >, selected: Array< SelectedIndex > }
selected-all手动勾选全选 Checkbox 时触发的事件,type="super"生效{ data: Array< CellData >, row: Array< ChangedRowIndex >, selected: Array< SelectedIndex > }
unselected-all手动取消全选 Checkbox 时触发的事件,type="super"生效{ data: Array< CellData >, row: Array< ChangedRowIndex >, selected: Array< SelectedIndex > }
sort排序条件发生变化时触发该事件Array<{name: String, order: 'asc|desc'}>
column-changed列设置改变后触发Array<{name: String, visible: Boolean, fixed: 'left|content|right' }>
editor-focus当editor变为选中态时触发{colIndex, rowIndex}
refresh开启pullrefresh下拉刷新时,触发下拉时触发,需要在该回调中调用stopPullRefresh关闭下拉刷新动效--
row-visited行被访问时(双击行)触发,仅type="super"生效{ visited: String | Number, rowData: Object }
row-activated行聚焦时触发,仅type="super"生效{ activated: String | Number, rowData: Object }
row-focused行hover时触发,仅type="super"生效{ focused: String | Number, rowData: Object }
row-dragend行拖动结束后触发,仅type="super"生效, 事件参数回返回排序后的数据{ data: Object, oldData: Object }
filter筛选条件改变时触发,仅type="super"生效Object
multipage-select-cleared点击清除跨页选择框中的已选中项后触发该事件{ data: Array, value: Any, selected: Array }
multipage-select-cleared-all点击跨页选择框中的清空按钮后触发该事件{ data: Array, selected: Array }

methods 方法

query

更改分页器的请求参数,并且重新发起请求, 可以一次传递多个。

  • 入参
1.undefined
保留当前 业务参数 页码 每页条数 请求方式 option ,达到刷新的效果,可用于页面返回后刷新数据

2.{}
清空业务参数(注意:并不是重置为初始值) 页码设置为1 保留每页条数 请求方式 option


3.<strong style="color:#ff0000">Tips:分页信息请勿在params中设置,比如:pageSize、currentPage等字段。如需设置请参考如下配置。</strong>
{
url:''// 请求url,如未设置使用上次的
params: {} ,// 业务请求参数,如未设置使用上次的
pageSize: 10 // 每页的数据条数,如未设置使用上次的
pageNum: 1 // 跳转的页码,如为传递则设置为1
httpMethod // 如未设置使用上次的
httpOptions// 如未设置使用上次的
}
示例

dml:
<table x='table1' ajax="http://testapi.dmall.com/testapi1">
...
</table>
js:
this.getComponent('table1').query({
url:http://testapi.dmall.com/testapi1
});
  • 出参:无

selectAll

selectable 开启后,选择所有checkbox

  • 入参:无
  • 出参:无
  • 使用:
dml:
<table x='table1' ajax="http://testapi.dmall.com/testapi1" :selectable={multiple:true}>
...
</table>
js:
this.getComponent('table1').selectAll()

unselectAll

selectable 开启后,取消所有checkbox

  • 入参:无
  • 入参:({ multipage: Boolean }) options 当输入对象中 multipage 为 ture 时,表示跨页清空所有checkbox
  • 出参:无
  • 使用:
dml:
<table x='table1' ajax="http://testapi.dmall.com/testapi1" :selectable={multiple:true}>
...
</table>
<table x='table2' selectable="{{ multiple: true, multipage: true, valueKey: 'name', labelKey: 'name'}}">
...
</table>
js:
this.getComponent('table1').unselectAll();
this.getComponent('table2').unselectAll({multipage: true});

unselect

selectable 开启后,取消选中

  • 入参:(rowNum: Array | Number) rowNum 行号
  • 出参:无
  • 使用:
dml:
<table x='table1' ajax="http://testapi.dmall.com/testapi1" :selectable={multiple:true}>
...
</table>
js:
this.getComponent('table1').unselect(0)
this.getComponent('table1').unselect([0,1,2,3])

select

selectable 开启后,选中

  • 入参:(rowNum: Array | Number) rowNum 行号
  • 出参:无
  • 使用:
  dml:
<table x='table1' ajax="http://testapi.dmall.com/testapi1" :selectable={multiple:true}>
...
</table>
js:
this.getComponent('table1').select(0)
this.getComponent('table1').select([0,1,2,3])
this.getComponent('table1').select([{rowNum:0, attrs:{disabled:true}},{rowNum:1, attrs:{disabled:true}}])

getData

获取表格的数据

  • 入参:无
  • 出参:
{
data : [], // 表格原始数据(为编辑)
selected : [],// selectable 开启后,得到选中行索引(从0开始),比如[0, 2]
edited:[], //editable 开启后,得到编辑过的数据
}

  • 使用:
  dml:
<table x='table1' ajax="http://testapi.dmall.com/testapi1" :selectable={multiple:true} editable>
...
</table>
js:
let tableData = this.getComponent('table1').getData();
console.log(tableData.data)
console.log(tableData.selected)
console.log(tableData.edited)

expandRow

展开行

  • 入参:(rowKey: String, callback: Function) 表格rowKey属性, callback 回调函数
  • 出参: 无
  • 使用:
  dml:
<table x='table' row-key="aggCode">
</table>
js:
this.getComponent('table').expandRow('AH01', () => {

});

getMultipageSelected

获取跨页选中项

  • 入参:无
  • 出参:Array<{label: String, value: Any}>
  • 使用:
    dml:
<table x='table1' selectable="{{ multiple: true, multipage: true, valueKey: 'name', labelKey: 'name'}}">
...
</table>
js:
const selected = this.getComponent('table1').getMultipageSelected();
console.log(selected)

focusEditor

选中并激活某个单元格

  • 入参:(rowIndex: Number, colIndex: Number | String) rowIndex 表格行的index, colIndex表格列的index,也可传入列的name
  • 出参:无
  • 使用:
    dml:
<table x='table1' editable>
...
</table>
js:
const table = this.getComponent('table1');
table.focusEditor(1,1);

activateRow

激活行,仅type="super"时可用

  • 入参:(rowNum: Number) rowNum 行号
  • 出参:无
  • 使用:
    dml:
<table x='table1'>
...
</table>
js:
this.getComponent('table1').activateRow(1);

focusRow

focus行,仅type="super"时可用

  • 入参:(rowNum: Number) rowNum 行号
  • 出参:无
  • 使用:
    dml:
<table x='table1'>
...
</table>
js:
this.getComponent('table1').focusRow(1);

stopPullRefresh

关闭下拉刷新的动效,仅移动端,type='super'和开启了pullrefresh时可用

  • 入参:无
  • 出参:无
  • 使用:
    dml:

<table x='table1'>
...
</table>
js:

onRefresh(){
setTimeout(() => {
this.getComponent('table1').stopPullRefresh();
}, 1000);
}

moveRows

上、下移动表格行

  • 入参:(selectedRows: Array | Number, offset: Number) selectedRows 选中的行号, offset 移动的偏移量
  • 出参:无
  • 使用:
    dml:

<table x='table1'>
...
</table>
js:

handleMove(offset) {
const table = this.getComponent('table');
const selected = table.getData().selected || [];
const hasSelected = !!selected.length;

if (hasSelected) {
table.moveRows(selected, offset);
}
},

scrollTo

表格滚动指定位置

  • 入参:(x: Number, y: Number) x 水平滚动距离, y 垂直滚动距离.
  • 入参:({rowIndex: Number}) rowIndex 指定的滚动的行
  • 出参:无
  • 使用:
    dml:

<table x='table1'>
...
</table>
js:

scrollTo(){
this.getComponent('table1').scrollTo(null, 120);
},
scrollToRowIndex() {
const rowIndex = 5;
this.getComponent('table1').scrollTo({ rowIndex });
},

expandRow

表格树形节点展开

  • 入参:(rowKey: String, callback: Function) rowKey 使用前要先配置表格属性row-key值对应的cell上的name并注意唯一性, callback 全部展开后回调函数.
  • 出参:无
  • 使用:
    dml:

<table x='table1' row-key="cellName">
...
</table>
js:

expandAllRow() {
this.getComponent('table1').expandRow(rowKey, (children)=>{
console.log(children)
});
},

collapseRow

表格树形节点收起

  • 入参:(rowKey: String) rowKey 使用前要先配置表格属性row-key值对应的cell上的name并注意唯一性
  • 出参:无
  • 使用:
    dml:

<table x='table1' row-key="cellName">
...
</table>
js:

expandAllRow() {
this.getComponent('table1').collapseRow(rowKey);
},

expandAllRow

表格树形全部节点展开

  • 入参:(callback: Function) 全部展开后回调函数.
  • 出参:无
  • 使用:
    dml:

<table x='table1'>
...
</table>
js:

expandAllRow() {
this.getComponent('table1').expandAllRow((expendRowKeys)=>{
console.log(expendRowKeys)
});
},

collapseAllRow

表格树形全部节点收起

  • 入参:(callback: Function) 全部收起后回调函数.
  • 出参:无
  • 使用:
    dml:

<table x='table1'>
...
</table>
js:

expandAllRow() {
this.getComponent('table1').collapseAllRow((collapseRowKeys)=>{
console.log(collapseRowKeys)
});
},

Slot

cell

列渲染逻辑,可配置属性:

参数说明类型可选值默认值
name调用getData()后这个字段在editd中的字段名(具体参考“编辑table”),
如不指定则会使用列号来标识
String
label列的标题String
sortable开启排序, 需要同时设置nameBooleanfalse
ellipsis开启超宽自动省略, 需要同时设置widthBooleanfalse
span跨行设置,内置'same',
自定义函数返回{ rowspan: Number, colspan: Number }
String|Function'same'\function(){}
align对齐方式Stringleft/center/rightleft
visible是否展示该列Booleantrue/falsetrue
tips提示String
type列类型,跨端该列会放在对应指定的位置Stringimage/title/tag/control
copiable开启单元格复制功能Boolean|{valueKey: String}false

cell type可选值

跨到移动端时,每行数据以卡片的形式展示,每个卡片分别由:主图区、标题区、标签区、内容区、快捷编辑区、操作区几个模块组成。其中有些区域需要用户明确指定,可通过cell的type属性配置,释义如下表:

参数说明必须
image主图,标明该列内容放在主图区,仅支持一列
title标题,标明该列内容放在标题区,仅支持一列移动端必须配置
tag标签,标明该列内容放在标签区,仅支持一列
control操作,标明该列内容放在操作区,仅支持一列

快捷编辑区:当cell内容为editor组件的前三个会放在快捷编辑区域。 内容区:除去上面其他区域的列会放在内容区域,内容区域支持1,2,3列三种排列布局,但无论哪种布局方式,内容最多不超过5行。

移动端每行的卡片默认点击可展示当前行的全部详细内容。如果table上监听了row-visited事件,点击卡片只会触发用户自定义事件,此时查看详情则需要手动配置show-more属性,点击更多区域打开详情。

cell内可用数据

{
"colIndex": 0, //列号
"rowIndex": 0, //行号
"colData": { "label": "No.", "fixed": "left" },//列头信息
//行数据
"rowData": { "date": "2016-05-03", "name": "王大虎", "province": "上海", "city": "普陀区", "address": "上海市普陀区金沙江路 1518 弄", "zip": "200333", "education": "本科", "occupation": "前端工程师" } }

empty

没有数据时候的展示

  • 示例:
dml:
<table x='table1' ajax="http://testapi.dmall.com/testapi1" :selectable={multiple:true} editable>
...
<empty>
没有数据...
<empty>
</table>

表格搜索

注意设置 initEmptyRow:false,否则搜索会有问题


<table x='table1' :searchBoxFilter='searchBoxFilter'>

</table>
export default Xpage({
showSearchBox() {
// 展示或者关闭搜索框
this.getComponent('table1').toggleSearchBox();
},
searchBoxFilter({ data, rowIndex, colIndex,colName, filterValue }) {
//自定义规则,根据 colName 等规则判断
//巨量表格可能会有性能问题

console.log(data)
if (colIndex === 1) {
return true;
}
return false;
},
});
属性说明类型可选值默认值版本
searchBoxFilter表格搜索回调方法Function({data,rowIndex,colIndex,colName,filterValue})----PC--

调用表格的 toggleSearchBox 方法 开启或者关闭搜索框;