Skip to content

Table组件 jb-table

table

jb-table组件是在VxeTable基础上扩展的,所以VxeTable中支持的属性在jb-table中都可以使用。另外也封装了 jb-column,用法同 VxeColumn

jb-table做了以下扩展:

  • 提供了一些默认配置
  • 全局格式化内容
  • 配合JBolt后端,提供了默认的表头指定列的按序查询功能
  • 提供了拖拽排序功能

默认配置

  • border: true 默认显示边框
  • height: true 默认高度自适应
  • showHeaderOverflow: tooltip 默认开启:表头内容过长时显示为省略号并显示tooltip
  • showOverflow: tooltip 默认开启:单元格内容过长时显示为省略号并显示tooltip
  • align: center 默认列内容居中对齐
  • row-config: {isHover: true,isCurrent: true,keyField: 'id',useKey: true} 默认开启行的hover和点击高亮,使用id字段作为行的key,并为每一行设置key属性
  • column-config: {resizable: true} 默认开启列宽调整功能
  • sortConfig : {remote:true} 默认开启后端按序查询功能,并提供了默认的按序查询逻辑。
  • seqConfig中的startIndex属性提取为组件的prop,方便配置。

基于以上配置,当我们使用<jb-table></jb-table>时,就相当于以下代码:

vue
<vxe-table align="center" :border="true" height="auto" 
    showHeaderOverflow="tooltip" showOverflow="tooltip" 
    :row-config="{isHover: true,isCurrent: true,keyField: 'id',useKey: true}"
    :column-config="{resizable: true}"       
    :sort-config="{remote:true}"
>
</vxe-table>
<vxe-table align="center" :border="true" height="auto" 
    showHeaderOverflow="tooltip" showOverflow="tooltip" 
    :row-config="{isHover: true,isCurrent: true,keyField: 'id',useKey: true}"
    :column-config="{resizable: true}"       
    :sort-config="{remote:true}"
>
</vxe-table>

全局格式化内容

使用 formats 添加格式函数,单元格会在渲染的时候自动调用

(用于实现业务中统一的格式化处理,这对于很多场景非常有用,减少很多不必要的重复代码)

ts
import { VXETable } from 'vxe-table'
import XEUtils from 'xe-utils'
// 格式化日期,默认 yyyy-MM-dd
VXETable.formats.add('date', {
  cellFormatMethod ({ cellValue }, format) {
    return XEUtils.toDateString(cellValue, format || 'yyyy-MM-dd')
  }
})
// 四舍五入金额,每隔3位逗号分隔,默认2位数
VXETable.formats.add('amount', {
  cellFormatMethod ({ cellValue }, digits = 2) {
    return XEUtils.commafy(XEUtils.toNumber(cellValue), { digits })
  }
})
// 格式化银行卡,默认每4位空格隔开
VXETable.formats.add('bankcard', {
  cellFormatMethod ({ cellValue }) {
    return XEUtils.commafy(XEUtils.toValueString(cellValue), { spaceNumber: 4, separator: ' ' })
  }
})
// 向下舍入,默认两位数
VXETable.formats.add('cutNumber', {
  cellFormatMethod ({ cellValue }, digits = 2) {
    return XEUtils.toFixed(XEUtils.floor(cellValue, digits), digits)
  }
})
// 四舍五入,默认两位数
VXETable.formats.add('fixedNumber', {
  cellFormatMethod ({ cellValue }, digits = 2) {
    return XEUtils.toFixed(XEUtils.round(cellValue, digits), digits)
  }
})
// 格式化性别
VXETable.formats.add('sex', {
  cellFormatMethod ({ cellValue }) {
    return cellValue ? (cellValue === '1' ? '男' : '女') : ''
  }
})
import { VXETable } from 'vxe-table'
import XEUtils from 'xe-utils'
// 格式化日期,默认 yyyy-MM-dd
VXETable.formats.add('date', {
  cellFormatMethod ({ cellValue }, format) {
    return XEUtils.toDateString(cellValue, format || 'yyyy-MM-dd')
  }
})
// 四舍五入金额,每隔3位逗号分隔,默认2位数
VXETable.formats.add('amount', {
  cellFormatMethod ({ cellValue }, digits = 2) {
    return XEUtils.commafy(XEUtils.toNumber(cellValue), { digits })
  }
})
// 格式化银行卡,默认每4位空格隔开
VXETable.formats.add('bankcard', {
  cellFormatMethod ({ cellValue }) {
    return XEUtils.commafy(XEUtils.toValueString(cellValue), { spaceNumber: 4, separator: ' ' })
  }
})
// 向下舍入,默认两位数
VXETable.formats.add('cutNumber', {
  cellFormatMethod ({ cellValue }, digits = 2) {
    return XEUtils.toFixed(XEUtils.floor(cellValue, digits), digits)
  }
})
// 四舍五入,默认两位数
VXETable.formats.add('fixedNumber', {
  cellFormatMethod ({ cellValue }, digits = 2) {
    return XEUtils.toFixed(XEUtils.round(cellValue, digits), digits)
  }
})
// 格式化性别
VXETable.formats.add('sex', {
  cellFormatMethod ({ cellValue }) {
    return cellValue ? (cellValue === '1' ? '男' : '女') : ''
  }
})

示例代码:

vue
    <jb-table :data="list">
        ...
        <jb-column field="createTime" title="日期" min-width="180" formatter="date"></jb-column>
        <jb-column field="money" title="金额" min-width="120" formatter="amount"></jb-column>
        <jb-column field="bankcard" title="银行卡" min-width="180" formatter="bankcard"></jb-column>
        <jb-column field="cutNumber" title="截取2位数" min-width="160" formatter="cutNumber"></jb-column>
        <jb-column field="fixedNumber" title="四舍五入2位数" min-width="160" formatter="fixedNumber"></jb-column>
        <jb-column field="sex" title="格式化性别" width="100" formatter="sex"></jb-column>
        ...
    </jb-table>
    <jb-table :data="list">
        ...
        <jb-column field="createTime" title="日期" min-width="180" formatter="date"></jb-column>
        <jb-column field="money" title="金额" min-width="120" formatter="amount"></jb-column>
        <jb-column field="bankcard" title="银行卡" min-width="180" formatter="bankcard"></jb-column>
        <jb-column field="cutNumber" title="截取2位数" min-width="160" formatter="cutNumber"></jb-column>
        <jb-column field="fixedNumber" title="四舍五入2位数" min-width="160" formatter="fixedNumber"></jb-column>
        <jb-column field="sex" title="格式化性别" width="100" formatter="sex"></jb-column>
        ...
    </jb-table>

默认的按序查询功能

前提条件:

  • jb-table需要在jb-crud-page下声明,jb-table的数据来源于jb-curd-page提供的list。参考这里
  • jb-crud-page 需要声明search-url属性
  • 后端对应search-url的接口需要支持根据sortTypesortColumn两个参数排序查询
  • 支持按序查询的列组件要声明sortable属性和field属性

jb-table下的jb-column声明了sortable属性时,就会开启该列的按序查询功能。 示例代码:

vue
<jb-crud-page
    search-url="/api/admin/demoTable/datas"
    :search-conditions="pageConditions"
>
    <template #default="{ list }">
        <jb-table :data="list">
            ...
            <jb-column field="age" title="年龄" width="100" sortable></jb-column>
            ...
        </jb-table>
    </template>
</jb-crud-page>
<jb-crud-page
    search-url="/api/admin/demoTable/datas"
    :search-conditions="pageConditions"
>
    <template #default="{ list }">
        <jb-table :data="list">
            ...
            <jb-column field="age" title="年龄" width="100" sortable></jb-column>
            ...
        </jb-table>
    </template>
</jb-crud-page>

示例

当点击排序按钮时,会自动调用jb-crud-page的查询功能。此时jb-crud-page会向search-url地址发起get请求,请求参数除了jb-crud-page组件上声明的search-conditions,还会额外附加sortTypesortColumn两个参数,后端需要根据这两个参数进行排序查询返回数据。

参数说明
sortTypeascdescnull排序类型,asc升序、desc降序、null取消排序
sortColumn排序按钮所在列声明的field属性值根据哪一个属性排序

拖拽排序功能

拖拽排序功能基于 vue-draggable-plus 第三方拖拽排序组件实现。目前使用上有以下限制:

  • 不支持空节点嵌入。比如有一个树形table,里面有一个节点a,a下面的子节点是空的,此时如果想把一个节点b拖拽到a下面成为a的子节点,是不支持的。
  • 不支持有固定列的table。因为固定列会通过渲染多个table实现,但拖拽只能在一个table上监听,导致拖拽时样式混乱、错位等问题发生。因此一旦开启拖拽,jb-table会强制取消列的固定,保证样式正常(需要配合jb-column使用)

开启拖拽排序需要的属性声明

属性说明
dragableboolean是否开启排序。一旦为true,会强制取消列的固定。
rankFieldstring数据中代表顺序的字段名
rowConfig.keyFieldstring,默认值id数据的唯一性标识字段名
treeConfig.childrenFieldstring如果是树表,要声明包含子节点的字段名,例如children或者items
onDragEnd(data:DragEndEventArgs):void | Promise<void>拖拽后的回调

示例

vue
<jb-table
                ref="tableRef"
                :tree-config="{
                    showLine: true,
                    childrenField: 'items',
                    reserve: true,
                    expandAll: true,
                    rowField: 'id'
                }"
                :data="data"
                :dragable="true"
                rank-field="sortRank"
                @drag-end="handleDragEnd"
            >
</jb-table>
<jb-table
                ref="tableRef"
                :tree-config="{
                    showLine: true,
                    childrenField: 'items',
                    reserve: true,
                    expandAll: true,
                    rowField: 'id'
                }"
                :data="data"
                :dragable="true"
                rank-field="sortRank"
                @drag-end="handleDragEnd"
            >
</jb-table>
ts
function handleDragEnd(data: DragEndEventArgs) {
    return JBoltApi.post('/api/admin/permission/changeSortRank', {
        id: data.id,
        oriPid: data.oriPid,
        oriRank: data.oriRank,
        newPid: data.newPid,
        newRank: data.newRank
    }).then(() => {
        return pageRef.value?.loadData()
    })
}
function handleDragEnd(data: DragEndEventArgs) {
    return JBoltApi.post('/api/admin/permission/changeSortRank', {
        id: data.id,
        oriPid: data.oriPid,
        oriRank: data.oriRank,
        newPid: data.newPid,
        newRank: data.newRank
    }).then(() => {
        return pageRef.value?.loadData()
    })
}

说明

  1. 拖拽后,jb-table会保持拖拽状态,但不会真的更改数据属性值。所以应该在onDragEnd回调函数中,将拖拽后的数据提交到后端,后端处理完成后,再重新加载最新数据。
  2. 拖拽后,jb-table会一直loading,阻止用户二次操作,直到onDragEnd回调函数执行完成。
  3. onDragEnd 回调函数参数说明:
参数名说明
id被拖拽的节点id,它的值根据 rowConfig中配置的keyField字段 获取
item被拖拽节点的完整数据
oriPid原父节点id值,非树形结构时为0
oriParentItem原父节点完整数据,非树形结构时为null
newPid新父节点id值,非树形结构时为0
newParentItem新父节点完整数据,非树形结构时为null
beforeItem拖拽完成后前一个元素的完整数据,null代表拖拽到最前面
oriRank拖拽前的顺序,它的值根据 rankField 字段获取
newRank拖拽后的顺序,它的值根据 rankField 字段获取