Appearance
表格
我们封装了 Table 组件、表格管家、TableManagerAPI 类、表头组件等,以方便快速生成和制作表格。
Table 组件
Table 组件位于 @/components/table/index.vue,我们基于 el-table 封装了该组件,所以 el-table 的所有事件属性都是可以直接在 Table 组件上使用的,部分属性可能失效,比如 el-table 的 size,这是因为 Table 组件拥有一些默认的 css 样式。
组件属性
| 属性名 | 注释 | 值 |
|---|---|---|
| manager | 表格管家实例 | TableManagerInstance |
| pagination | 是否显示底部分页组件 | boolean |
| ... | 其他 el-table 的属性可以直接使用 | - |
组件方法与事件
| 方法名/项目 | 注释 |
|---|---|
| getElTableRef | 获取内部 el-table 的 ref,通过它调用 el-table 的原有方法 |
| toggleExpansionAll | 折叠/展开表格(树状表格特有) |
| 其他各类事件 | 单双击、勾选、hover、右击等事件 el-table 均以自带,请转到 el-table 事件文档 |
组件插槽
| 插槽名 | 注释 | 子标签 |
|---|---|---|
| header | 表头与表格主体中间区域 | 任意 |
| columnPrepend | 通过此插槽在 表格管家实例 中定义的列之前插入列 | el-table-column |
| columnAppend | 通过此插槽在 表格管家实例 中定义的列之后插入列 | el-table-column |
| footer | 表格底部区域 | 任意 |
| 任意 | 列支持使用 render:slot, slotName: 插槽名称 来使用 slot 渲染 | 任意 |
TIP
Table 组件和下方的表格管家是搭配使用的,管家为表格提供数据,并可以响应表格组件的各种事件,Table 组件的使用示例放在了下方表格管家示例一起。
表格管家
- 代码位于:
@/hooks/useTableManager,之所以没有放在@/components/table/目录内,因为table组件还依赖API请求函数(放在了@/api/table),拆开放是不可避免和合理的。 - 我们在表格管家里面封装好了一个表格应有的
属性和方法,预设了查看前、查看后、编辑前等钩子,几乎和表格相关的所有数据和操作都可以找它。
TIP
表格管家本质是一个工厂函数,非常强大和重要,我们在 表格管家的深度理解 一节对这一点进行了强调说明。
使用示例
以下为基本使用示例,它的实际使用可以非常灵活,请发挥您的想象力;表格管家支持的属性在 表格所有可用属性 有介绍,您还可以直接查阅 src\hooks\useTableManager.ts 文件代码(有注释,不知道有哪些属性可用时,可查看 ts 的类型定义)
切换以下代码块的 Tab 来查看不同文件的示例代码。
ts
<script setup lang="ts">
import { TableManagerAPI } from '@/api/table' // 导入表格 API 方法生成器类
import TableHeader from '@/components/table/header/index.vue' // 导入单独的表格表头组件
import { getDefaultOptButtons } from '@/components/table/index'
import Table from '@/components/table/index.vue' // 导入 Table 组件
import { useTableManager } from '@/hooks/useTableManager' // 导入表格管家
import { useI18n } from 'vue-i18n'
import DialogForm from './dialogForm.vue' // 独立表单组件,方便二开,它接受并使用了表格管家的数据、提交方法等,但并无强耦合
const { t } = useI18n()
// 获取默认的 [编辑, 删除] 操作按钮,按钮数据其实就是一个 ts 数组,可以随便改
const optButtons = getDefaultOptButtons(['edit', 'delete'])
const tableManager = useTableManager({
// 一个 API 类的实例,该类可快速生成一个控制器的 增、删、改、查、排序 接口的请求方法
api: new TableManagerAPI('/admin/test/'),
table: {
// 支持使用 [render: 'slot', slotName: '插槽名称'] 来指定插槽渲染,<Table> 组件本身也有一些其他可以放表格列的插槽
column: [
{ type: 'selection', align: 'center', operator: false },
{ label: 'ID', prop: 'id', align: 'center', operator: 'BETWEEN', width: 70, sortable: 'custom' },
{
label: '用户名',
prop: 'username',
align: 'center',
operator: 'ILIKE',
sortable: false,
quickSearch: true,
showOverflowTooltip: true,
},
{ label: '操作', align: 'center', width: 100, render: 'buttons', buttons: optButtons, operator: false },
],
// 默认排序
filter: {
sort: 'id',
order: 'desc',
},
// 不需要 【双击编辑】的列
dblClickNotEditColumn: ['switch'],
// ...... 属性很多,请参考本文下方的表格全部可用属性,或翻阅源代码(有注释)
},
form: {
// 添加表单的字段默认值
defaultItems: {
string: 'test',
},
},
})
onMounted(() => {
tableManager.table.ref = tableRef.value
tableManager.initCtx()
tableManager.getData()?.then(() => {
// 拖拽排序需要在获取到表格数据之后,才能初始化
// 如果需要拖拽排序则调用,否则可直接精简为 onMounted 之外执行 tableManager.initCtx() / tableManager.getData() 两行即可
tableManager.initDragSort()
})
})
</script>vue
<template>
<div class="default-main">
<TableHeader
:manager="tableManager"
v-model:com-search="tableManager.comSearch"
:buttons="['refresh', 'add', 'edit', 'delete', 'comSearch', 'quickSearch', 'columnDisplay']"
/>
<!-- 可以直接在标签上使用 el-table 的属性和事件 -->
<Table ref="tableRef" :manager="tableManager">
<!-- 插槽语法自定义列 -->
<template #columnPrepend>
<el-table-column prop="prepend" label="第一个列" width="180" />
</template>
<!-- 表格管理实例中定义的表格列会渲染在此处 -->
</Table>
<DialogForm :manager="tableManager" v-model:form-items="tableManager.form.items!" />
</div>
</template>vue
<!-- 独立的表单组件 + 尽量原生的语法,以便二次开发 -->
<!-- 本组件接受表格管家实例,并使用了实例上的 `数据` 和 `表单提交方法`,并无强耦合 -->
<template>
<el-dialog
class="ag-operate-dialog"
:close-on-click-modal="false"
:model-value="['create', 'update'].includes(manager.form.operate!)"
@close="manager.toggleForm"
:destroy-on-close="true"
:draggable="true"
>
<template #header>
<div class="title">
{{ manager.form.operate == 'create' ? t('common.add') : t('common.edit') }}
</div>
</template>
<el-scrollbar v-loading="manager.form.loading" class="ag-table-form-scrollbar">
<div
class="ag-operate-form"
:class="'ag-' + manager.form.operate + '-form'"
:style="config.layout.shrink ? '' : 'width: calc(100% - ' + manager.form.labelWidth! / 2 + 'px)'"
>
<el-form
ref="formRef"
@keyup.enter="manager.submitForm(formRef)"
:model="formItems"
:label-position="config.layout.shrink ? 'top' : 'right'"
:label-width="manager.form.labelWidth + 'px'"
:rules="rules"
v-if="!manager.form.loading"
>
<el-form-item :label="t('test.username')" prop="username">
<el-input v-model="formItems.username" :placeholder="t('common.pleaseEnter', { field: t('test.username') })" />
</el-form-item>
<el-form-item :label="t('common.weigh')" prop="weigh">
<el-input-number
class="w100"
controls-position="right"
v-model="formItems.weigh"
:placeholder="t('common.pleaseEnter', { field: t('common.weigh') })"
/>
</el-form-item>
</el-form>
</div>
</el-scrollbar>
<template #footer>
<div :style="'width: calc(100% - ' + manager.form.labelWidth! / 1.8 + 'px)'">
<el-button @click="manager.toggleForm()">{{ t('common.cancel') }}</el-button>
<el-button :loading="manager.form.submitLoading" @click="manager.submitForm(formRef)" type="primary">
{{ manager.form.operatePKs && manager.form.operatePKs.length > 1 ? t('common.saveAndContinue') : t('common.save') }}
</el-button>
</div>
</template>
</el-dialog>
</template>
<script setup lang="ts">
import { useConfig } from '@/stores/config'
import { buildValidatorRule } from '@/utils/validate'
import type { FormItemRule } from 'element-plus'
import { useTemplateRef } from 'vue'
import { useI18n } from 'vue-i18n'
interface Props {
manager: TableManagerInstance
}
defineProps<Props>()
const formItems = defineModel<AnyObj>('formItems', { required: true })
const config = useConfig()
const formRef = useTemplateRef('formRef')
const { t } = useI18n()
const rules: Partial<Record<string, FormItemRule[]>> = {
username: [buildValidatorRule({ name: 'required', title: t('test.username') })],
}
</script>
<style scoped lang="scss"></style>表格列
此处特指实例化表格管家(useTableManager())时定义的列(table.column)数据,如下:
ts
import { useTableManager } from '@/hooks/useTableManager'
import { TableManagerAPI } from '@/api/table'
const tableManager = useTableManager({
api: new TableManagerAPI('/admin/test/'),
table: {
// 表格列数据,其中 type、align、operator 等称为列属性,所有可用属性可在下方查阅
// 支持使用 [render: 'slot', slotName: '插槽名称'] 来指定插槽渲染,<Table> 组件本身也有一些其他可以放表格列的插槽
column: [
{ type: 'selection', align: 'center', operator: false },
{ label: 'ID', prop: 'id', align: 'center', operator: 'BETWEEN', width: 70, sortable: 'custom' },
{
label: '用户名',
prop: 'username',
align: 'center',
operator: 'ILIKE',
sortable: false,
quickSearch: true,
showOverflowTooltip: true,
},
{ label: '操作', align: 'center', width: 140, render: 'buttons', buttons: optButtons, operator: false },
],
},
})表格列的可用属性
切换以下代码块的 Tab 来查看多份示例代码。
ts
interface TableColumn extends Partial<TableColumnCtx<TableRow>> {
// 是否于表格显示此列
show?: boolean
// 渲染器组件名,即 \src\components\table\cellRenderer\ 中的组件之一,也可以查看 TableCellRenderer 类型定义获取渲染器列表
render?: TableCellRenderer
// 字典数据(值替换数据),同时用于单元格渲染和公共搜索下拉框数据,格式如: { open: '开', close: '关', disable: '已禁用' }
dict?: Record<string, any>
// render=slot 时,slot 的名称
slotName?: string
// render=customRender 时,要渲染的组件或已注册组件名称的字符串
customRender?: string | Component
// render=customTemplate 时,自定义渲染 html,应谨慎使用: 请返回 html 内容,务必确保返回内容是 xss 安全的
customTemplate?: (row: TableRow, columnConfig: TableColumn, column: TableColumnCtx<TableRow>, cellValue: any, index: number) => string
// 渲染前对字段值的预处理函数(对 el-table 的 formatter 扩展)
formatter?: (row: TableRow, column: TableColumnCtx<TableRow>, cellValue: any, index: number) => any
/**
* 自定义单元格渲染属性(比如单元格渲染器内部的 tag、button 组件的属性,设计上不仅是组件属性,也可以自定义其他渲染相关属性)
* 直接定义对应组件的属性 object,或使用一个函数返回组件属性 object
*/
customRenderAttr?: {
tag?: TableContextDataFun<TagProps>
icon?: TableContextDataFun<InstanceType<typeof Icon>['$props']>
image?: TableContextDataFun<ImageProps>
switch?: TableContextDataFun<SwitchProps>
tooltip?: TableContextDataFun<ElTooltipProps>
link?: TableContextDataFun<LinkProps>
[key: string]: any
}
// render=buttons 时,按钮数据数组
buttons?: OptButton[]
/**
* 单元格渲染器需要的其他任意自定义数据
* 1. render=tag 时,可单独指定每个不同的值 tag 的 type 属性 { open: 'success', close: 'info', disable: 'danger' }
* 2. render=datetime 时,可指定时间日期的格式化模板(dayjs().format 模板,如 { format: 'YYYY-MM-DD HH:mm:ss' })
*/
custom?: {
format?: string
[key: string]: any
}
// 默认值(单元格值为 undefined,null,'' 时取默认值,仅使用了 render 时有效)
default?: any
// 作为快速搜索字段之一
quickSearch?: boolean
// 是否允许动态控制字段是否显示,默认为 true
columnDisplayControl?: boolean
// 单元格渲染组件的 key,默认将根据列配置等属性自动生成(此 key 值改变时单元格将自动重新渲染)
getRenderKey?: (row: TableRow, columnConfig: TableColumn, column: TableColumnCtx<TableRow>, index: number) => string
// 操作符(一般用于公共搜索),默认值为 = ,值为 false 禁用此字段公共搜索,支持的操作符见下类型定义
operator?: boolean | OperatorStr
// 公共搜索框的 placeholder
comSearchPlaceholder?: string | string[]
// 公共搜索渲染方式,render=tag|switch 时公共搜索也会渲染为下拉,数字会渲染为范围筛选等
comSearchRender?: 'string' | 'remoteSelect' | 'select' | 'time' | 'date' | 'datetime' | 'customRender' | 'slot'
// 公共搜索自定义渲染为 slot 时,slot 的名称
comSearchSlotName?: string
// 公共搜索自定义组件/函数渲染
comSearchCustomRender?: string | Component
// 公共搜索自定义渲染时,外层 el-col 的属性(仅 customRender、slot 支持)
comSearchColAttr?: Partial<ColProps>
// 公共搜索是否显示字段的 label
comSearchShowLabel?: boolean
// 公共搜索输入组件的扩展属性
comSearchInputAttr?: AnyObj
// 公共搜索渲染为远程下拉时,远程下拉组件的必要属性
comSearchRemote?: {
pk?: string
field?: string
multiple?: boolean
pagination?: boolean
remoteURL: string
remoteParams?: AnyObj
remoteSearchFields?: string[]
}
}ts
/**
* 可用的表格单元格渲染器,以 ./src/components/table/cellRenderer/ 目录中的文件名自动生成
*/
type TableCellRenderer =
| 'buttons'
| 'color'
| 'customRender'
| 'customTemplate'
| 'datetime'
| 'icon'
| 'image'
| 'images'
| 'switch'
| 'tag'
| 'tags'
| 'url'
| 'slot'ts
type OperatorStr =
| 'eq' // 等于,默认值
| 'ne' // 不等于
| 'gt' // 大于
| 'egt' // 大于等于
| 'lt' // 小于
| 'elt' // 小于等于
| 'LIKE'
| 'NOT LIKE'
| 'ILIKE'
| 'NOT ILIKE'
| 'IN'
| 'NOT IN'
| 'BETWEEN' // 范围,将生成两个输入框,可以输入最小值和最大值
| 'NOT BETWEEN'
| 'NULL' // 是否为NULL,将生成单个复选框
| 'NOT NULL'自定义单元格渲染
我们预设了一系列的单元格渲染方式 image、switch、tag...,若它们不能满足您的需求,我们提供了另外四种方案,最终方案实现了完全的自定义渲染能力。
切换以下代码块的 Tab 来查看多份示例代码。
ts
import { TableManagerAPI } from '@/api/table'
import { useTableManager } from '@/hooks/useTableManager'
// 在您使用预设的单元格渲染方案时(`switch|image|tag...`),可以在渲染前,通过函数对单元格值进行一次处理:
const tableManager = useTableManager({
api: new TableManagerAPI('/admin/test/'),
table: {
column: [
{
label: 'ID',
prop: 'id',
align: 'center',
width: 70,
formatter(row, column, cellValue, index) {
return cellValue + ' - 为该列所有值,加了个后缀'
},
},
],
},
})vue
<template>
<div class="default-main">
<Table ref="tableRef" :manager="tableManager">
<!-- 请注意 #test 它是自定义的插槽名称 -->
<template #test>
<!-- 在插槽内,您可以随意发挥,通常使用 el-table-column 组件 -->
<el-table-column prop="username" label="用户名" width="180" />
<!-- 还可以继续使用 el-table-column 组件本身的插槽 -->
<el-table-column prop="id" label="ID" width="180">
<template #default="scope">
<b>{{ scope.row['id'] }}</b>
列宽度是:{{ scope.column.width }}
</template>
</el-table-column>
</template>
</Table>
</div>
</template>
<script setup lang="ts">
const tableManager = useTableManager({
api: new TableManagerAPI('/admin/test/'),
table: {
column: [
{ label: '管理员', render: 'slot', slotName: 'test', operator: 'LIKE' },
],
},
})
</script>ts
import { h, resolveComponent } from 'vue'
// renderId 即自定义的组件,你也可以直接单独建立一个 vue 文件导入使用
// 自定义组件可以接受五个 props,分别是:renderRow=当前行数据,renderColumnConfig=当前列配置数据,renderValue=单元格值,renderColumn=当前列上下文数据,renderIndex=当前行号,manager=表格管家实例
const renderId = {
render(context: any) {
console.log(
context.$attrs.renderRow,
context.$attrs.renderColumnConfig,
context.$attrs.renderValue,
context.$attrs.renderColumn,
context.$attrs.renderIndex,
context.$attrs.manager
)
// 使用原生元素渲染,如`div、h1、a`等,以下演示了将 单元格值 直接通过h1标签进行渲染
return h('h1', { class: 'id-h1' }, context.$attrs.renderValue)
// 使用vue组件定义进行渲染(导入的组件)
return h(Foo, { onClick: () => {} }, context.$attrs.renderValue)
// 使用vue组件定义进行渲染(全局注册的组件)
return h(resolveComponent('el-xxx'), context.$attrs.renderValue)
},
}
const tableManager = useTableManager({
api: new TableManagerAPI('/admin/test/'),
table: {
column: [
{ label: 'id', prop: 'id', render: 'customRender', customRender: h(renderId) }
],
},
})ts
// 您还可以直接建立 image、switch 等系统同级的单元格渲染器,全局使用
// 请查阅 src\components\table\cellRenderer 文件夹,其中的每个组件为一种单元格渲染器
// 组件名称即为渲染器名称,可直接将组件名于 useTableManager.column.render 配置使用
// 假设您参考已有渲染器建立了 src\components\table\cellRenderer\customRenderId.vue 组件,可如下,直接于 useTableManager.column 配置使用
// 建立了新的单元格渲染器后,重新执行 pnpm dev,系统还会自动更新可用渲染器的类型定义,以获得语法提示支持
// 此处不再提供渲染器内部的代码示例,因为系统已经自带了很多个定义好的,请直接复制文件->改名->修改->使用
const tableManager = useTableManager({
api: new TableManagerAPI('/admin/test/'),
table: {
column: [
{ label: 'id', prop: 'id', render: 'customRenderId' }
],
},
})自定义表格顶部按钮
有时您需要自定义表格顶部的按钮,请直接 点击此处查看示例代码。
自定义表格行侧边按钮
表格行侧边的按钮组通过普通的 ts 数组进行配置,所以自定义它非常容易,因为您只需对一个 ts 数组进行增删改查操作;常用的按钮配置数组可通过 getDefaultOptButtons() 快速生成。
切换以下代码块的 Tab 来查看多份示例代码。
ts
import { TableManagerAPI } from '@/api/table'
import { useTableManager } from '@/hooks/useTableManager'
import { getDefaultOptButtons } from '@/components/table/index'
// getDefaultOptButtons 函数返回默认按钮数据
const optButtons = getDefaultOptButtons(['edit', 'delete'])
// 给第一个按钮加上点击事件
optButtons[0].click = (row: TableRow, field: TableColumn) => {
console.log('点击了按钮')
}
// 自定义一个新的按钮
let newButton: OptButton = {
render: 'tip',
name: 'copy',
icon: 'lucide-database-arrow-down',
type: 'success',
title: '复制',
class: 'table-row-copy',
click: (row) => {
console.log(row)
},
}
// 新按钮合入到默认的按钮数组
optButtons.push(newButton)
const tableManager = useTableManager({
api: new TableManagerAPI('/admin/test/'),
table: {
column: [{ label: t('common.operate'), align: 'center', width: 100, render: 'buttons', buttons: optButtons, operator: false }],
},
})
tableManager.initCtx()
tableManager.getData()ts
interface OptButton {
/**
* 渲染方式:basic=普通按钮,tip=带提示的按钮,confirm=带确认框的按钮,sort=拖动排序按钮
*/
render: 'basic' | 'tip' | 'confirm' | 'sort'
/**
* 按钮名称,同时将作为触发表格内事件(onTableAction)时的事件名
*/
name: string
/**
* 鼠标 hover 时的提示
*/
title?: string
/**
* 直接在按钮内显示的文字,可为空
*/
text?: string
/**
* 自定义按钮的点击事件
* @param row 当前行数据
* @param column 当前列数据
*/
click?: (row: TableRow, column: TableColumn) => void
/**
* 按钮是否显示(请返回布尔值,比如: display: auth('create'))
* @param row 当前行数据
* @param column 当前列数据
*/
display?: (row: TableRow, column: TableColumn) => boolean
/**
* 按钮是否禁用(请返回布尔值)
* @param row 当前行数据
* @param column 当前列数据
*/
disabled?: (row: TableRow, column: TableColumn) => boolean
/**
* 按钮是否正在加载中(请返回布尔值)
* @param row 当前行数据
* @param column 当前列数据
*/
loading?: (row: TableRow, column: TableColumn) => boolean
/**
* 自定义 el-button 的其他属性(格式为属性 object 或一个返回属性 object 的函数)
*/
attr?: TableContextDataFun<ButtonProps>
// 按钮 class
class?: string
// 按钮 type
type: ButtonType
// 按钮 icon 的名称
icon: string
// 确认按钮的气泡确认框的属性(el-popconfirm 的属性,格式为属性 object 或一个返回属性 object 的函数)
popconfirm?: TableContextDataFun<PopconfirmProps>
// 是否禁用 title 提示,此值通常由系统动态调整以确保提示的显示效果
disabledTip?: boolean
}手动拼装表格筛选数据
TIP
公共搜索表单数据 != 查询筛选数据,它们可以分别设定。- 预设的条件数据可能被覆盖,比如用户
点击公共搜索、使用快速搜索时,为保障用户实时需求,会直接覆盖所有筛选条件,如需固定筛选数据,首选服务端,其次是利用钩子函数。
切换以下代码块的 Tab 来查看多份示例代码。
ts
import { TableManagerAPI } from '@/api/table'
import { useTableManager } from '@/hooks/useTableManager'
const tableManager = useTableManager({
api: new TableManagerAPI('/admin/test/'),
table: {column: []},
})
// 先调用管家的基础上下文初始化函数
tableManager.initCtx()
// 准备一个 wheres 容器
const groups: WhereGroup[] = []
// 设定【公共搜索表单数据】
// id 字段是范围筛选,以逗号分割多个值,此处支持同时传递多个字段的值
tableManager.setComSearchData({ id: '1,2' })
// 获取【公共搜索表单数据】,结果为拼接好的 where 数据(自动根据列的 operator 和 comSearchRender 组装好对应的 where)
const com = tableManager.getComSearchData()
if (com !== false) {
// 将 where 数据合入容器
groups.push(com)
}
// 如果有快速搜索关键词
if (tableManager.table.filter!.quickSearchKeywords) {
const quick = tableManager.getQuickSearchData(tableManager.table.filter!.quickSearchKeywords)
if (quick !== false) {
// 将快速搜索的 where 数据合入容器
groups.push(quick)
}
}
// 设定列表请求时的 where 数据
tableManager.setFilterWheres(groups)
// 执行查看请求
tableManager.getData()ts
import { TableManagerAPI } from '@/api/table'
import { useTableManager } from '@/hooks/useTableManager'
const tableManager = useTableManager({
api: new TableManagerAPI('/admin/test/'),
table: {
column: [],
filter: {
// 大组,大组与大组之间固定使用 AND 连接
wheres: [
{
// 小组,小组与小组之间可以指定连接符号,通过如下 or 属性
wheres: [
{
field: 'id',
value: [1, 2],
operator: 'IN',
},
],
or: false,
},
],
},
},
form: {},
})ts
import { TableManagerAPI } from '@/api/table'
import { useTableManager } from '@/hooks/useTableManager'
const tableManager = useTableManager({
api: new TableManagerAPI('/admin/test/'),
table: {
column: [],
filter: {
// 排序字段
sort: 'id',
// 排序方式
order: 'desc',
wheres: [
// 第一大组 where
{
wheres: [
{
field: 'id',
value: [1, 2],
operator: 'IN',
},
{
field: 'string',
value: '字符串1',
operator: 'ILIKE',
},
],
// 第一大组 where 内的多个 where 之间是否使用 OR 连接: false=不使用,true=使用
or: false,
},
// 第二大组 where,与第一组的查询连接符号固定为 AND(即大组之间不能指定连接符号,但小组之间可以自定义)
{
wheres: [
{
field: 'id',
value: [1, 2],
operator: 'IN',
},
{
field: 'string',
value: '字符串1',
operator: 'ILIKE',
},
],
// 第二大组 where 内的多个 where 之间是否使用 OR 连接: false=不使用,true=使用
or: true,
},
],
},
},
form: {},
})表格操作前后置钩子
TIP
钩子不是事件,事件请参考 Element Plus 官方文档,如单击单元格、双击、勾选、鼠标 hover、右击、列宽度改变等事件 el-table 本身均已自带实现。
切换以下代码块的 Tab 来查看多份示例代码。
ts
const tableManager = useTableManager({
api: new TableManagerAPI('/admin/test/'),
table: { column: [] },
})
// 获取表格数据前的钩子
tableManager.opts.before!.getData = () => {
tableManager.table.expandAll = tableManager.table.filter!.quickSearchKeywords ? true : false
}
// 获取到编辑行数据后钩子
tableManager.opts.after!.getEditData = () => {
if (tableManager.form.items && !tableManager.form.items.icon) {
tableManager.form.items.icon = 'lucide-circle-small'
}
}ts
interface TableManagerBefore {
/**
* 获取表格数据前的钩子(返回 false 可取消原操作)
*/
getData?: () => boolean | void
/**
* 获取被编辑行数据前的钩子(返回 false 可取消原操作)
* @param object.pk 被编辑行主键
*/
getEditData?: ({ pk }: { pk: string }) => boolean | void
/**
* 删除前的钩子(返回 false 可取消原操作)
* @param object.pks 被删除数据的主键集合
*/
delete?: ({ pks }: { pks: string[] }) => boolean | void
/**
* 双击表格具体操作执行前钩子(返回 false 可取消原操作)
* @param object.row 被双击行数据
* @param object.column 被双击列数据
*/
columnDblclick?: ({ row, column }: { row: TableRow; column: TableColumn }) => boolean | void
/**
* 表单切换前钩子(返回 false 可取消默认行为)
* @param object.operate 当前操作标识:create=添加,update=更新
* @param object.operatePKs 被操作的行的主键集合
*/
toggleForm?: ({ operate, operatePKs }: { operate: string; operatePKs: string[] }) => boolean | void
/**
* 表单提交前钩子(返回 false 可取消原操作)
* @param object.formEl 表单组件ref
* @param object.operate 当前操作标识:create=添加,update=更新
* @param object.items 表单数据
*/
submitForm?: ({ formEl, operate, items }: { formEl?: FormInstance | null; operate: string; items: AnyObj }) => boolean | void
/**
* 表格内事件响应前钩子(返回 false 可取消原操作)
* @param object.event 事件名称
* @param object.data 事件携带的数据
*/
tableEvent?: ({ event, data }: { event: TableEventName; data: AnyObj }) => boolean | void
/**
* 表格上下文数据初始化前钩子
*/
initCtx?: () => boolean | void
// 可自定义其他钩子
[key: string]: Function | undefined
}ts
interface TableManagerAfter {
/**
* 请求到表格数据后钩子
* 此时 useTableManager.table.data 已赋值
* @param object.res 请求完整响应
*/
getData?: ({ res }: { res: ApiResponse }) => void
/**
* 获取到编辑行数据后钩子
* 此时 useTableManager.form.items 已赋值
* @param object.res 请求完整响应
*/
getEditData?: ({ res }: { res: ApiResponse }) => void
/**
* 删除请求后钩子
* @param object.res 请求完整响应
*/
delete?: ({ res }: { res: ApiResponse }) => void
/**
* 双击单元格操作执行后钩子
* @param object.row 当前行数据
* @param object.column 当前列数据
*/
columnDblclick?: ({ row, column }: { row: TableRow; column: TableColumn }) => void
/**
* 表单切换后钩子
* @param object.operate 当前操作标识:create=添加,update=更新
* @param object.operatePKs 被操作的主键集合
*/
toggleForm?: ({ operate, operatePKs }: { operate: string; operatePKs: string[] }) => void
/**
* 表单提交后钩子
* @param object.res 请求完整响应
*/
submitForm?: ({ res }: { res: ApiResponse }) => void
/**
* 表格内事件响应后钩子
* @param object.event 事件名称
* @param object.data 事件携带的数据
*/
tableEvent?: ({ event, data }: { event: TableEventName; data: AnyObj }) => void
// 可自定义其他钩子
[key: string]: Function | undefined
}表格管家的深度理解
类如其名,作为表格的管家:
- 你可以找它拿数据,比如
表格行数据、当前被编辑行的数据、公共搜索表单数据、快速搜索关键词、当前表单操作标识、加载状态、页码、每页显示数等,几乎与表格相关的所有数据都能从这里拿到。 - 你可以找它更新数据,你能拿到的数据自然也能直接修改,这些数据通常都具备响应性。
- 你可以找它做操作,比如
刷新表格、发起公共/快速搜索、调整排序、分页、打开编辑表单等。 - 监控与拦截操作,几乎所有事件均可拦截或监控,比如
获取表格数据前后、获取编辑行数据前后、双击单元格前后、打开/提交表单、刷新、删除等,除我们定义的钩子外,el-table也内置有各种单击、双击、hover 事件。 - 随时待命,通过表格管家实例你可以在代码任何位置对任意属性进行修改。
- 高度可定制化,您可以随时重写它的方法,追加自定义扩展数据(方便数据随整个类在上下文中流通)等,想怎么改就怎么改。
- 它是一个
ts工厂函数,但更是表格状态商店,是表格事件巴士,是万能入口与工具库,它是真正的好管家。
以下是一些使用示例:
ts
// 您可以先设置好一些表格属性,再获取表格数据
// 表格所有可用属性本文下方有:https://doc.ai-go-hub.com/senior/web/table.html#%E8%A1%A8%E6%A0%BC%E6%89%80%E6%9C%89%E5%8F%AF%E7%94%A8%E5%B1%9E%E6%80%A7
const example1 = () => {
// 修改显示条数和页码
tableManager.table.filter!.limit = 20
tableManager.table.filter!.page = 2
// 仅示例,实际场景中【设置查看请求的筛选数据】是自动完成的
const com = tableManager.getComSearchData() // 获取当前公共搜索数据
if (com !== false) {
tableManager.setFilterWheres([com]) // 设置查看请求的筛选数据
}
// 最后再获取数据
tableManager.getData()
}ts
// 数据加载完成后打开公共搜索
tableManager.getData()?.then(() => {
tableManager.table.showComSearch = true
})ts
/**
* 利用钩子在修改数据前对数据进行预处理
*/
tableManager.opts.after!.getEditData = () => {
if (tableManager.form.items && !tableManager.form.items.icon) {
tableManager.form.items.icon = 'lucide-circle-small'
}
}ts
import { auth } from '/@/utils/common'
// 重写表格内部验权方法
tableManager.auth = (node) => {
return auth({ name: '/admin/auth/group' })
}
// auth 是全局公共函数,它的文档请参考:https://doc.ai-go-hub.com/senior/web/utils.html#%E5%89%8D%E7%AB%AF%E9%89%B4%E6%9D%83
// tableManager.auth 是表格内部鉴权方法,参数 node 是表格内部需要鉴权的节点,比如 create、update、delete 等ts
// 参数类型是 AnyObj,框架本身未对参数进行任何识别处理,只是习惯性传递
tableManager.refresh({ event: 'submit-form', items: items })表格所有可用属性
ts
// 一般通过 useTableManager.table.* 访问
interface TableInterface {
/**
* 表格数据,通过 useTableManager.getData 获取
* 刷新数据可使用 useTableManager.refresh({ event: 'custom' })
*/
data?: TableRow[]
/**
* 表格列定义
*/
column: TableColumn[]
/**
* 获取表格数据时的过滤条件(含公共搜索、快速搜索、分页、排序等数据)
* 公共搜索数据可使用 useTableManager.setComSearchData 和 useTableManager.getComSearchData 进行管理
*/
filter?: {
page?: number
limit?: number
sort?: string
order?: 'desc' | 'asc'
wheres?: WhereGroup[]
quickSearchKeywords?: string
[key: string]: any
}
/**
* 不需要双击编辑的列;
* 禁用全部列的双击编辑,可使用 ['all'];
* type=selection 的列为 undefined,将自动禁用
*/
dblClickNotEditColumn?: string[]
/**
* 表格扩展数据,随意定义,以便一些自定义数据可以随 useTableManager 实例传递
*/
extend?: AnyObj
// 表格 ref,通常在页面 onMounted 时赋值,可选的
ref?: InstanceType<typeof Table> | null
// 表格对应数据表的主键字段,默认 id
pk?: string
// 表格加载状态
loading?: boolean
// 当前选中行
selections?: TableRow[]
// 数据总量
total?: number
// 接受 url 的 query 参数并自动触发公共搜索
acceptQuery?: boolean
// 显示公共搜索
showComSearch?: boolean
// 是否展开所有子项,树状表格专用属性
expandAll?: boolean
// 当前表格所在页面的路由 path
routePath?: string
// 拖动排序限位字段,例如拖动行 pid=1,那么拖动目的行 pid 也需要为 1
dragSortLimitField?: string
// 拖动排序权重字段,进行拖拽排序时,必需先以此字段排序,系统将修改此字段的值来完成新顺序落盘,留空则取 `weigh`
dragSortWeighField?: string
}ts
// 一般通过 useTableManager.form.* 访问
interface FormInterface {
/**
* 当前表单项数据
*/
items?: AnyObj
/**
* 当前表单操作标识:create=添加,update=更新
*/
operate?: string
/**
* 添加表单字段默认值,打开表单时会使用 cloneDeep 赋值给 useTableManager.form.items 对象
*/
defaultItems?: AnyObj
/**
* 表单扩展数据,可随意定义,以便一些自定义数据可以随 useTableManager 实例传递
*/
extend?: AnyObj
// 表单 ref,实例化表格时通常无需传递
ref?: FormInstance | null
// 表单项 label 的宽度
labelWidth?: number
// 被操作数据主键,支持批量更新:create=[],update=[1,2,n]
operatePKs?: string[]
// 提交按钮状态
submitLoading?: boolean
// 表单数据的加载状态
loading?: boolean
}ts
// 一般通过 useTableManager.comSearch.* 访问
interface ComSearchInterface {
// 公共搜索表单项数据
form: AnyObj
// 字段搜索配置,搜索操作符(operator)、公共搜索渲染方式(comSearchRender)、字段渲染方式(render)
fieldData: Map<string, any>
}ts
// 一般通过 useTableManager.table.column[index].* 访问
interface TableColumn extends Partial<TableColumnCtx<TableRow>> {
// 是否于表格显示此列
show?: boolean
// 渲染器组件名,即 \src\components\table\cellRenderer\ 中的组件之一,也可以查看 TableCellRenderer 类型定义获取渲染器列表
render?: TableCellRenderer
// 字典数据(值替换数据),同时用于单元格渲染和公共搜索下拉框数据,格式如: { open: '开', close: '关', disable: '已禁用' }
dict?: Record<string, any>
// render=slot 时,slot 的名称
slotName?: string
// render=customRender 时,要渲染的组件或已注册组件名称的字符串
customRender?: string | Component
// render=customTemplate 时,自定义渲染 html,应谨慎使用: 请返回 html 内容,务必确保返回内容是 xss 安全的
customTemplate?: (row: TableRow, columnConfig: TableColumn, column: TableColumnCtx<TableRow>, cellValue: any, index: number) => string
// 渲染前对字段值的预处理函数(对 el-table 的 formatter 扩展)
formatter?: (row: TableRow, column: TableColumnCtx<TableRow>, cellValue: any, index: number) => any
/**
* 自定义单元格渲染属性(比如单元格渲染器内部的 tag、button 组件的属性,设计上不仅是组件属性,也可以自定义其他渲染相关属性)
* 直接定义对应组件的属性 object,或使用一个函数返回组件属性 object
*/
customRenderAttr?: {
tag?: TableContextDataFun<TagProps>
icon?: TableContextDataFun<InstanceType<typeof Icon>['$props']>
image?: TableContextDataFun<ImageProps>
switch?: TableContextDataFun<SwitchProps>
tooltip?: TableContextDataFun<ElTooltipProps>
link?: TableContextDataFun<LinkProps>
[key: string]: any
}
// render=buttons 时,按钮数据数组
buttons?: OptButton[]
/**
* 单元格渲染器需要的其他任意自定义数据
* 1. render=tag 时,可单独指定每个不同的值 tag 的 type 属性 { open: 'success', close: 'info', disable: 'danger' }
* 2. render=datetime 时,可指定时间日期的格式化模板(dayjs().format 模板,如 { format: 'YYYY-MM-DD HH:mm:ss' })
*/
custom?: {
format?: string
[key: string]: any
}
// 默认值(单元格值为 undefined,null,'' 时取默认值,仅使用了 render 时有效)
default?: any
// 作为快速搜索字段之一
quickSearch?: boolean
// 是否允许动态控制字段是否显示,默认为 true
columnDisplayControl?: boolean
// 单元格渲染组件的 key,默认将根据列配置等属性自动生成(此 key 值改变时单元格将自动重新渲染)
getRenderKey?: (row: TableRow, columnConfig: TableColumn, column: TableColumnCtx<TableRow>, index: number) => string
// 操作符(一般用于公共搜索),默认值为 = ,值为 false 禁用此字段公共搜索,支持的操作符见下类型定义
operator?: boolean | OperatorStr
// 公共搜索框的 placeholder
comSearchPlaceholder?: string | string[]
// 公共搜索渲染方式,render=tag|switch 时公共搜索也会渲染为下拉,数字会渲染为范围筛选等
comSearchRender?: 'string' | 'remoteSelect' | 'select' | 'time' | 'date' | 'datetime' | 'customRender' | 'slot'
// 公共搜索自定义渲染为 slot 时,slot 的名称
comSearchSlotName?: string
// 公共搜索自定义组件/函数渲染
comSearchCustomRender?: string | Component
// 公共搜索自定义渲染时,外层 el-col 的属性(仅 customRender、slot 支持)
comSearchColAttr?: Partial<ColProps>
// 公共搜索是否显示字段的 label
comSearchShowLabel?: boolean
// 公共搜索输入组件的扩展属性
comSearchInputAttr?: AnyObj
// 公共搜索渲染为远程下拉时,远程下拉组件的必要属性
comSearchRemote?: {
pk?: string
field?: string
multiple?: boolean
pagination?: boolean
remoteURL: string
remoteParams?: AnyObj
remoteSearchFields?: string[]
}
}ts
/**
* 公共搜索事件返回的 Data
* 同时也是发送给服务端的单条 Where 条件类型定义
*/
interface ComSearchData {
field: string
value: string | string[] | number | number[]
operator: string
}
/**
* Where 查询条件分组
* 服务端对 `字段是否存在、操作符合是否合法` 进行检查,并对 `值` 使用 `预处理语句参数占位符` 拼接
*/
interface WhereGroup {
wheres: ComSearchData[]
or?: boolean // 组内条件是否使用 OR 连接,值为 false 则使用 AND 连接条件
}表格公共搜索
- 表格公共搜索就是列的公共搜索,所以它在定义
tableManager.table.column列数据时设定,主要是表格列的operator、comSearchRender、其他以 comSearch* 开头的属性共同参与公共搜索框的渲染。 - 公共搜索表单源码位置
src\components\table\header\comSearch.vue,其本质很简单:遍历column,根据operator、comSearchRender渲染一个表单出来。
如下示例代码:
ts
const tableManager = useTableManager({
api: new TableManagerAPI('/admin/test/'),
table: {
column: [
{
label: '性别',
prop: 'gender',
align: 'center',
// 公共搜索渲染为 select
comSearchRender: 'select',
// 字典数据,它将作为 select 的选项列表(同时也是单元格渲染时的值替换列表)
dict: { '0': '未知', '1': '女', '2': '男' },
// 公共搜索操作符号
operator: 'eq',
// 单元格渲染为 tag
render: 'tag',
},
],
},
})operator
即公共搜索操作符号,支持的符号有:
ts
type OperatorStr =
| 'eq' // 等于,默认值
| 'ne' // 不等于
| 'gt' // 大于
| 'egt' // 大于等于
| 'lt' // 小于
| 'elt' // 小于等于
| 'LIKE' // 模糊查询
| 'NOT LIKE'
| 'ILIKE' // 不区分大小写的模糊查询
| 'NOT ILIKE'
| 'IN'
| 'NOT IN'
| 'BETWEEN' // 范围,将生成两个输入框,可以输入最小值和最大值
| 'NOT BETWEEN'
| 'NULL' // 是否为NULL,将生成单个复选框
| 'NOT NULL'
| false其中比较常见的用法是:
operator=false则表示关闭此字段的公共搜索operator=ILIKE不区分大小写的模糊匹配operator=BETWEEN为范围查询,生成两个输入框(一般是对数字或时间日期使用)
operator 和 show 属性配合使用
有时,您可能需要同一列有两次配置机会,比如在公共搜索和表格中使用不同的 label,如下 id 的 公共搜索 和 单元格渲染 的配置完全独立,一个配置用于表格、一个配置用于公共搜索。
ts
column: [
{ label: 'ID-公共搜索', prop: 'id', show: false, operator: 'LIKE' },
{ label: 'ID-列表显示', prop: 'id', operator: false, width: 70 },
]comSearchRender
comSearchRender 指定公共搜索渲染方案,支持 remoteSelect、select、time、date 等,特别是最终保底方案还可以将公共搜索渲染为 slot,即自定义插槽渲染,您可以在插槽内部选择自己喜欢的输入框和样式,详细使用方法:公共搜索配置示例代码、完全自定义公共搜索的渲染。
公共搜索输入组件渲染示意表
| comSearchRender | operator | 公共搜索渲染 |
|---|---|---|
| 任意 | false | 关闭公共搜索,不渲染 |
| 任意 | BETWEEN、NOT BETWEEN | 生成 A-B 两个输入框,可搜索 从 A 到 B 的范围值 |
| 任意 | NULL、NOT NULL | 生成一个复选框,勾选则搜索值为 NULL、NOT NULL 的情况 |
| remoteSelect | eq、ne、gt 等比较符号,可参考 operator | 远程下拉,需通过 comSearchRemote 设定好远程下拉的必填属性 |
| select | eq、ne、gt 等比较符号 | 下拉框,选项列表请参考 表格列 的 dict 字典数据 |
| time | eq、ne、gt 等比较符号 | 时间选择器(纯时间) |
| time | BETWEEN、NOT BETWEEN | 时间范围选择器(纯时间) |
| date | eq、ne、gt 等比较符号 | 日期选择器(纯日期无时间) |
| date | BETWEEN、NOT BETWEEN | 日期范围选择器(纯日期无时间) |
| datetime | eq、ne、gt 等比较符号 | 时间日期选择器 |
| datetime | BETWEEN、NOT BETWEEN | 时间日期范围选择器 |
| string | 任意 | 字符串输入框(它还是默认的公共搜索渲染方案) |
| customRender | 任意 | 自定义渲染组件或 slot,请参考下方示例 |
公共搜索配置示例代码
ts
import { useTableManager } from '@/hooks/useTableManager'
import { TableManagerAPI } from '@/api/table'
const tableManager = useTableManager({
api: new TableManagerAPI('/admin/test/'),
table: {
// 定义表格列数据、同时定义公共搜索数据
column: [
// 关闭这个字段的公共搜索
{ type: 'selection', align: 'center', operator: false },
// 此字段是模糊查找,并为公共搜索输入框设置了 placeholder
{ label: 'ID', prop: 'id', align: 'center', operator: 'ILIKE', comSearchPlaceholder: '模糊搜索', width: 70 },
// 此字段是图片,建议关闭公共搜索
{ label: '头像', prop: 'avatar', align: 'center', render: 'image', operator: false },
// 此字段将生成一个下拉框选择进行搜索,拥有三个值
{
label: '性别',
prop: 'gender',
align: 'center',
render: 'tag',
comSearchRender: 'select',
dict: { 'unknown': '未知', 'male': '男', 'woman': '女' },
},
// 此字段将生成一个时间范围选择框,选择时间日期进行搜索
{
label: '创建时间',
prop: 'createtime',
align: 'center',
render: 'datetime',
sortable: 'custom',
comSearchRender: 'datetime',
operator: 'BETWEEN',
width: 160,
},
// 此字段将生成一个日期范围选择框,选择日期进行搜索(请注意渲染还是 datetime 若需自定义单元格渲染请参考 `表格列` 一节)
{
label: '创建时间',
prop: 'updatetime',
align: 'center',
render: 'datetime',
sortable: 'custom',
operator: 'BETWEEN',
width: 160,
comSearchRender: 'date',
},
// 远程下拉选择框
{
label: '会员',
prop: 'user_id',
comSearchRender: 'remoteSelect',
comSearchRemote: {
// 主键,下拉 value
pk: 'id',
// 字段,下拉 label
field: 'username',
// 远程接口URL
// 比如想要获取 admin(管理员)表的数据,后台 管理员管理 列表方法 的 URL 为 /admin/auth/admin/list
remoteURL: '/admin/auth/admin/list',
// 额外的请求参数
remoteParams: {},
},
},
],
},
})自动获取表格筛选条件
有时您需要通过 URL 带着一些筛选条件跳转到表格,实现直接获取筛选后的数据(直接在 URL 中填写公共搜索数据),如:/#/admin/auth/admin?username=test&id=2,3
只要 URL 中的 query 字段名和表格列名对应,且该列开启了公共搜索,URL 上的参数,可以被自动获取到并作为公共搜索的筛选条件。
如下是跳转时拼接 query 的方法,手动字符串拼接也是可以的。
ts
import router from '@/router/index'
// 跳转到 auth/admin 页面,并携带 id 和 username 参数
router.push({
name: 'auth/admin',
query: {
// id 和 username 字段存在于 auth/admin 页面表格的公共搜索中
// auth/admin 页面内的表格公共搜索,会自动获取下列参数,如果在列定义中存在则自动填充并搜索
id: '2,3', // 范围搜索使用 , 号分割
username: 'test',
},
})完全自定义公共搜索的渲染
切换以下代码块的 Tab 来查看多份示例代码。
vue
<template>
<div class="default-main">
<TableHeader
:manager="tableManager"
v-model:com-search="tableManager.comSearch"
:buttons="['refresh', 'add', 'edit', 'delete', 'comSearch', 'quickSearch', 'columnDisplay']"
>
<!-- 请注意 #test 它是自定义的插槽名称 -->
<template #test>
<!-- 在插槽内,您可以随意发挥,通常渲染一个输入框供用户输入内容 -->
<!-- 输入组件的 v-model="baTable.comSearch.form[item.prop!]" 即可在baTable上下文获取用户输入的关键词 -->
我是公共搜索的slot渲染内容
</template>
</TableHeader>
<Table :manager="tableManager" />
</div>
</template>
<script setup lang="ts">
import { TableManagerAPI } from '@/api/table'
import TableHeader from '@/components/table/header/index.vue'
import Table from '@/components/table/index.vue'
import { useTableManager } from '@/hooks/useTableManager'
const tableManager = useTableManager({
api: new TableManagerAPI('/admin/test/'),
table: {
// 定义表格列数据、同时定义公共搜索数据
column: [
// comSearchRender: 'slot' 表示本字段的公共搜索将使用 slot 渲染
// comSearchSlotName: 'test' 填写自定义好的 slot 的名称
{ label: '管理员', prop: 'username', operator: 'LIKE', comSearchRender: 'slot', comSearchSlotName: 'test' },
],
},
})
</script>ts
import { h, resolveComponent } from 'vue'
// searchId 即自定义的组件,你也可以直接单独建立一个 vue 文件导入使用
// 自定义组件可以接受三个 props,分别是:renderColumnConfig=列表配置数据,renderColumnProp=列数据,renderValue=搜索框绑定值,manager=表格管家实例
const searchId = {
render(context: any) {
console.log(context.$attrs.renderColumnConfig, context.$attrs.renderColumnProp, context.$attrs.renderValue, context.$attrs.manager)
// 使用原生元素渲染
return h('input', { class: 'id-h1' }, context.$attrs.renderValue)
// 使用vue组件定义进行渲染(全局注册的组件)
return h(resolveComponent('el-input'), context.$attrs.renderValue)
},
}
const tableManager = useTableManager({
api: new TableManagerAPI('/admin/test/'),
table: {
// 定义表格列数据、同时定义公共搜索数据
column: [
{ label: 'id', prop: 'id', comSearchRender: 'customRender', comSearchCustomRender: h(searchId) }
],
},
})vue
<!-- 1. 表格顶部菜单的 buttons 里边不要有 comSearch,表示不启用默认的公共搜索 -->
<TableHeader
:manager="tableManager"
v-model:com-search="tableManager.comSearch"
:buttons="['refresh', 'add', 'edit', 'delete', 'quickSearch', 'columnDisplay']"
></TableHeader>
<!-- 2. 完整实现一个自定义的公共搜索组件并导入使用 -->
<!-- 3. 通过 tableManager.table.showComSearch 来判断您自定义公共搜索组件的显示隐藏状态 -->
<ComSearch v-if="tableManager.table.showComSearch"></ComSearch>TableManagerAPI 类
此类代码位于:@/src/api/table.ts,它实现快速生成一个控制器的:增、删、改、查、排序 的操作 URL 和请求方法,提供控制器的根 URL 即可。此类通常与表格管家搭配使用,若需单独定义 API 请求函数,可以直接在 \src\api 目录下定义,无需经过 TableManagerAPI。
使用示例
vue
<script>
import { TableManagerAPI } from '@/api/table'
const api = new TableManagerAPI('/admin/test/')
// 修改请求地址 - 只修改地址不能满足需求的,可直接于 \src\api 目录下自定义请求函数后导入使用,可参考网络请求文档
api.actionURL.set('get', '/admin/test/get-new')
api.actionURL.set('list', '/admin/test/list-new')
api.actionURL.set('create', '/admin/test/create-new')
api.actionURL.set('update', '/admin/test/update-new')
api.actionURL.set('delete', '/admin/test/delete-new')
api.actionURL.set('sort', '/admin/test/sort-new')
/**
* 主动执行请求
* 注意:TableManagerAPI 类的方法通常都是供 useTableManager 使用的,以下仅为方便读者理解它是什么,一般无需主动执行
*/
api.list({}) // 请求 list,参数为筛选条件,具体使用请参考 useTableManager
api.post({}) // 向指定接口 post 数据
api.delete({}) // 请求删除,参数为被删除数据的 ids
// ...
const tableManager = useTableManager({
api: api,
table: {},
})
</script>表格顶部组件
TableHeader 组件内含有公共搜索和表头操作按钮,菜单按钮可以自动根据当前路由进行 鉴权,当前管理员无权限的按钮,则不会显示。
属性列表
| 属性名 | 注释 |
|---|---|
| manager | 表格管家实例 |
| buttons | 要显示的按钮数组,比如 ['refresh', 'add', 'comSearch'],即表示于表格顶部显示 刷新、添加、公共搜索 按钮 |
| quick-search-placeholder | 快速搜索输入框的 placeholder |
插槽列表
| 插槽名 | 注释 |
|---|---|
| refreshPrepend | 刷新按钮前插槽 |
| refreshAppend | 刷新按钮后插槽 |
| — | 此插槽内容将放置在组件内置的菜单按钮之后,可自定义表格顶部按钮等 |
| quickSearchPrepend | 快速搜索前插槽 |
| 任意 | 列配置中使用 comSearchRender:'slot', comSearchSlotName: '插槽名称' 来通过 slot 渲染公共搜索 |
支持的菜单按钮
| 菜单按钮 | 注释 |
|---|---|
| refresh | 刷新按钮 |
| add | 添加 |
| edit | 编辑 |
| delete | 删除 |
| comSearch | 公共搜索 |
| quickSearch | 快速搜索 |
| columnDisplay | 字段显示状态切换组件 |
| rowExpansion | 展开/折叠,与 useTableManager.table.expandAll 属性关联 |
表格顶部菜单示例代码
vue
<template>
<div>
<TableHeader
:manager="tableManager"
v-model:com-search="tableManager.comSearch"
:buttons="['refresh', 'add', 'edit', 'delete', 'comSearch', 'quickSearch', 'columnDisplay']"
>
<!-- 可以在此处以插槽的方式设置一些自定义按钮 -->
<template #refreshPrepend>
<!-- 刷新按钮前插槽内容 -->
</template>
<!-- 默认插槽 -->
<template #default>
<el-button :disabled="tableManager.table.selections!.length > 0 ? false : true" class="table-header-operate" type="success">
<Icon color="#ffffff" size="18" name="el-refresh-right" />
<!-- 自定义了一个还原按钮 -->
<span class="table-header-operate-text">还原</span>
</el-button>
</template>
</TableHeader>
</div>
</template>
<script>
import TableHeader from '@/components/table/header/index.vue'
</script>常见问题
如何禁用列的双击编辑功能?
我们可以通过添加列的 prop 到 useTableManager.table.dblClickNotEditColumn 数组,来禁用对应列的双击编辑功能,当我们想禁用全部列的双击编辑功能时只需要定义 dblClickNotEditColumn: ['all'] 即可。
