Skip to content

ProTable 增强表格

ProTable 是一个增强版的表格组件,集成了搜索、分页、列设置等功能,适用于中后台管理系统。

基础用法

最基础的表格展示用法。

vue
<template>
  <NProTable :columns="columns" :data="data" />
</template>

<script setup>
const columns = [
  { prop: 'name', label: '姓名' },
  { prop: 'age', label: '年龄' },
  { prop: 'address', label: '地址' },
]

const data = [
  { id: 1, name: '张三', age: 20, address: '北京市' },
  { id: 2, name: '李四', age: 25, address: '上海市' },
  { id: 3, name: '王五', age: 30, address: '广州市' },
]
</script>

请求数据

通过 requestApi 属性传入请求函数,自动获取数据。

vue
<template>
  <NProTable :columns="columns" :requestApi="getData" />
</template>

<script setup>
const columns = [
  { prop: 'name', label: '姓名' },
  { prop: 'age', label: '年龄' },
  { prop: 'address', label: '地址' },
]

const getData = async (params) => {
  // 模拟 API 请求
  const { pageNum = 1, pageSize = 10 } = params
  const list = [
    { id: 1, name: '张三', age: 20, address: '北京市' },
    { id: 2, name: '李四', age: 25, address: '上海市' },
    { id: 3, name: '王五', age: 30, address: '广州市' },
  ]
  return {
    data: {
      list: list.slice((pageNum - 1) * pageSize, pageNum * pageSize),
      total: list.length,
    },
  }
}
</script>

搜索表单

在列配置中设置 search 属性来启用搜索功能。

vue
<template>
  <NProTable :columns="columns" :requestApi="getData" />
</template>

<script setup>
const columns = [
  {
    prop: 'name',
    label: '姓名',
    search: {
      el: 'input',
      label: '姓名',
      order: 1,
    },
  },
  {
    prop: 'status',
    label: '状态',
    search: {
      el: 'select',
      label: '状态',
      order: 2,
    },
    enum: [
      { label: '启用', value: 1 },
      { label: '禁用', value: 0 },
    ],
  },
  {
    prop: 'createTime',
    label: '创建时间',
    search: {
      el: 'date-picker',
      label: '创建时间',
      order: 3,
    },
  },
  { prop: 'address', label: '地址' },
]

const getData = async (params) => {
  // 模拟 API 请求
  return {
    data: {
      list: [],
      total: 0,
    },
  }
}
</script>

多选

设置 type="selection" 来启用多选功能。

vue
<template>
  <NProTable
    ref="proTableRef"
    :columns="columns"
    :data="data"
  >
    <template #tableHeader="{ selectedList, isSelected }">
      <NButton :disabled="!isSelected" type="primary">
        删除 ({{ selectedList.length }})
      </NButton>
    </template>
  </NProTable>
</template>

<script setup>
import { ref } from 'vue'
const proTableRef = ref(null)

const columns = [
  { type: 'selection' },
  { prop: 'name', label: '姓名' },
  { prop: 'age', label: '年龄' },
  { prop: 'address', label: '地址' },
]

const data = [
  { id: 1, name: '张三', age: 20, address: '北京市' },
  { id: 2, name: '李四', age: 25, address: '上海市' },
  { id: 3, name: '王五', age: 30, address: '广州市' },
]
</script>

索引列

设置 type="index" 来显示索引列。

vue
<template>
  <NProTable :columns="columns" :data="data" />
</template>

<script setup>
const columns = [
  { type: 'index' },
  { prop: 'name', label: '姓名' },
  { prop: 'age', label: '年龄' },
  { prop: 'address', label: '地址' },
]

const data = [
  { id: 1, name: '张三', age: 20, address: '北京市' },
  { id: 2, name: '李四', age: 25, address: '上海市' },
  { id: 3, name: '王五', age: 30, address: '广州市' },
]
</script>

操作列

使用 render 属性来自定义操作列。

vue
<template>
  <NProTable :columns="columns" :data="data" />
</template>

<script setup>
const columns = [
  { prop: 'name', label: '姓名' },
  { prop: 'age', label: '年龄' },
  { prop: 'address', label: '地址' },
  {
    label: '操作',
    prop: 'operation',
    render: (scope) => (
      <div>
        <el-button type="primary" link>
          编辑
        </el-button>
        <el-button type="danger" link>
          删除
        </el-button>
      </div>
    ),
  },
]

const data = [
  { id: 1, name: '张三', age: 20, address: '北京市' },
  { id: 2, name: '李四', age: 25, address: '上海市' },
  { id: 3, name: '王五', age: 30, address: '广州市' },
]
</script>

列设置

设置 toolButton 属性来启用列设置功能。

vue
<template>
  <NProTable
    :columns="columns"
    :data="data"
    :toolButton="['refresh', 'setting', 'search']"
  />
</template>

<script setup>
const columns = [
  { prop: 'name', label: '姓名' },
  { prop: 'age', label: '年龄' },
  { prop: 'address', label: '地址' },
]

const data = [
  { id: 1, name: '张三', age: 20, address: '北京市' },
  { id: 2, name: '李四', age: 25, address: '上海市' },
  { id: 3, name: '王五', age: 30, address: '广州市' },
]
</script>

自定义表头

使用 headerRender 属性来自定义表头。

vue
<template>
  <NProTable :columns="columns" :data="data" />
</template>

<script setup>
const columns = [
  {
    prop: 'name',
    label: '姓名',
    headerRender: (scope, column) => (
      <div>
        <span>{column.label}</span>
        <el-tooltip content="这是姓名列">
          <el-icon style="margin-left: 4px;"><QuestionFilled /></el-icon>
        </el-tooltip>
      </div>
    ),
  },
  { prop: 'age', label: '年龄' },
  { prop: 'address', label: '地址' },
]

const data = [
  { id: 1, name: '张三', age: 20, address: '北京市' },
  { id: 2, name: '李四', age: 25, address: '上海市' },
  { id: 3, name: '王五', age: 30, address: '广州市' },
]
</script>

隐藏列

设置 isShow 属性为 false 来隐藏列。

vue
<template>
  <NProTable :columns="columns" :data="data" />
</template>

<script setup>
const columns = [
  { prop: 'name', label: '姓名' },
  { prop: 'age', label: '年龄' },
  { prop: 'address', label: '地址', isShow: false },
]

const data = [
  { id: 1, name: '张三', age: 20, address: '北京市' },
  { id: 2, name: '李四', age: 25, address: '上海市' },
  { id: 3, name: '王五', age: 30, address: '广州市' },
]
</script>

禁用列设置

设置 isSetting 属性为 false 来禁止列设置。

vue
<template>
  <NProTable :columns="columns" :data="data" />
</template>

<script setup>
const columns = [
  { prop: 'name', label: '姓名', isSetting: false },
  { prop: 'age', label: '年龄' },
  { prop: 'address', label: '地址' },
]

const data = [
  { id: 1, name: '张三', age: 20, address: '北京市' },
  { id: 2, name: '李四', age: 25, address: '上海市' },
  { id: 3, name: '王五', age: 30, address: '广州市' },
]
</script>

标签列

设置 tag 属性为 true 来显示标签样式。

vue
<template>
  <NProTable :columns="columns" :data="data" />
</template>

<script setup>
const columns = [
  { prop: 'name', label: '姓名' },
  {
    prop: 'status',
    label: '状态',
    tag: true,
    enum: [
      { label: '启用', value: 1, tagType: 'success' },
      { label: '禁用', value: 0, tagType: 'danger' },
    ],
  },
  { prop: 'address', label: '地址' },
]

const data = [
  { id: 1, name: '张三', status: 1, address: '北京市' },
  { id: 2, name: '李四', status: 0, address: '上海市' },
  { id: 3, name: '王五', status: 1, address: '广州市' },
]
</script>

展开行

设置 type="expand" 和使用 expand 插槽来实现展开行。

vue
<template>
  <NProTable :columns="columns" :data="data">
    <template #expand="{ row }">
      <div style="padding: 16px;">
        <p>姓名: {{ row.name }}</p>
        <p>年龄: {{ row.age }}</p>
        <p>地址: {{ row.address }}</p>
      </div>
    </template>
  </NProTable>
</template>

<script setup>
const columns = [
  { type: 'expand' },
  { prop: 'name', label: '姓名' },
  { prop: 'age', label: '年龄' },
  { prop: 'address', label: '地址' },
]

const data = [
  { id: 1, name: '张三', age: 20, address: '北京市' },
  { id: 2, name: '李四', age: 25, address: '上海市' },
  { id: 3, name: '王五', age: 30, address: '广州市' },
]
</script>

拖拽排序

设置 type="sort" 来启用拖拽排序。

vue
<template>
  <NProTable :columns="columns" :data="data" @dragSort="handleDragSort" />
</template>

<script setup>
const columns = [
  { type: 'sort' },
  { prop: 'name', label: '姓名' },
  { prop: 'age', label: '年龄' },
  { prop: 'address', label: '地址' },
]

const data = ref([
  { id: 1, name: '张三', age: 20, address: '北京市' },
  { id: 2, name: '李四', age: 25, address: '上海市' },
  { id: 3, name: '王五', age: 30, address: '广州市' },
])

const handleDragSort = ({ newIndex, oldIndex }) => {
  console.log('拖拽排序:', newIndex, oldIndex)
}
</script>

禁用分页

设置 paginationfalse 来禁用分页。

vue
<template>
  <NProTable :columns="columns" :data="data" :pagination="false" />
</template>

<script setup>
const columns = [
  { prop: 'name', label: '姓名' },
  { prop: 'age', label: '年龄' },
  { prop: 'address', label: '地址' },
]

const data = [
  { id: 1, name: '张三', age: 20, address: '北京市' },
  { id: 2, name: '李四', age: 25, address: '上海市' },
  { id: 3, name: '王五', age: 30, address: '广州市' },
]
</script>

自定义分页大小

使用 pageSizes 属性来自定义分页大小选项。

vue
<template>
  <NProTable :columns="columns" :data="data" :pageSizes="[5, 10, 20, 50]" />
</template>

<script setup>
const columns = [
  { prop: 'name', label: '姓名' },
  { prop: 'age', label: '年龄' },
  { prop: 'address', label: '地址' },
]

const data = [
  { id: 1, name: '张三', age: 20, address: '北京市' },
  { id: 2, name: '李四', age: 25, address: '上海市' },
  { id: 3, name: '王五', age: 30, address: '广州市' },
]
</script>

初始请求参数

使用 initParam 属性来设置初始请求参数。

vue
<template>
  <NProTable :columns="columns" :requestApi="getData" :initParam="initParam" />
</template>

<script setup>
const columns = [
  { prop: 'name', label: '姓名' },
  { prop: 'age', label: '年龄' },
  { prop: 'address', label: '地址' },
]

const initParam = {
  status: 1,
  type: 'all',
}

const getData = async (params) => {
  console.log('请求参数:', params)
  return {
    data: {
      list: [],
      total: 0,
    },
  }
}
</script>

数据回调

使用 dataCallback 属性来处理请求返回的数据。

vue
<template>
  <NProTable :columns="columns" :requestApi="getData" :dataCallback="dataCallback" />
</template>

<script setup>
const columns = [
  { prop: 'name', label: '姓名' },
  { prop: 'age', label: '年龄' },
  { prop: 'address', label: '地址' },
]

const getData = async (params) => {
  return {
    code: 200,
    data: {
      records: [],
      total: 0,
    },
  }
}

const dataCallback = (data) => {
  return {
    list: data.records,
    total: data.total,
  }
}
</script>

请求错误处理

使用 requestError 属性来处理请求错误。

vue
<template>
  <NProTable :columns="columns" :requestApi="getData" :requestError="requestError" />
</template>

<script setup>
const columns = [
  { prop: 'name', label: '姓名' },
  { prop: 'age', label: '年龄' },
  { prop: 'address', label: '地址' },
]

const getData = async (params) => {
  throw new Error('请求失败')
}

const requestError = (error) => {
  console.error('请求错误:', error)
}
</script>

禁用自动请求

设置 requestAutofalse 来禁用自动请求。

vue
<template>
  <NProTable
    ref="proTableRef"
    :columns="columns"
    :requestApi="getData"
    :requestAuto="false"
  />
  <NButton @click="handleSearch">手动请求</NButton>
</template>

<script setup>
import { ref } from 'vue')
const proTableRef = ref(null)

const columns = [
  { prop: 'name', label: '姓名' },
  { prop: 'age', label: '年龄' },
  { prop: 'address', label: '地址' },
]

const getData = async (params) => {
  return {
    data: {
      list: [],
      total: 0,
    },
  }
}

const handleSearch = () => {
  proTableRef.value.getTableList()
}
</script>

API

Props

属性说明类型默认值
columns列配置ColumnProps[][]
data静态数据any[]
requestApi获取数据的 API(params: any) => Promise<any>
requestAuto是否自动执行请求booleantrue
requestError请求错误回调(params: any) => void
dataCallback数据回调,可以处理数据(data: any) => any
title表格标题string
pagination是否显示分页booleantrue
initParam初始化请求参数any{}
border是否显示边框booleantrue
toolButton工具栏按钮('refresh' | 'setting' | 'search')[] | booleantrue
rowKey行数据的 Keystring'id'
pageSizes分页大小选项number[][10, 25, 50, 100]

ColumnProps

属性说明类型默认值
type列类型'index' | 'selection' | 'radio' | 'expand' | 'sort'
prop字段名称string
label列标题string
width列宽度string | number
minWidth列最小宽度string | number
fixed列是否固定boolean | 'left' | 'right'false
sortable对应列是否可以排序boolean | 'custom'false
align对齐方式'left' | 'center' | 'right''left'
headerAlign表头对齐方式'left' | 'center' | 'right'
showOverflowTooltip当内容过长被隐藏时显示 tooltipbooleanfalse
tag是否显示标签样式boolean | Ref<boolean>false
isShow是否显示列boolean | Ref<boolean>true
isSetting是否允许列设置boolean | Ref<boolean>true
search搜索配置SearchProps
enum枚举数据EnumProps[] | Ref<EnumProps[]> | ((params?: any) => Promise<any>)
isFilterEnum是否过滤枚举boolean | Ref<boolean>true
fieldNames字段名映射FieldNamesProps
headerRender自定义表头渲染(scope: HeaderRenderScope, column?: any) => VNode
render自定义渲染(scope: RenderScope) => VNode | string
_children子列配置ColumnProps[]
tooltip提示信息string

SearchProps

属性说明类型默认值
el搜索组件类型'input' | 'input-number' | 'select' | 'select-v2' | 'tree-select' | 'cascader' | 'date-picker' | 'time-picker' | 'time-select' | 'switch' | 'slider''input'
label搜索标签string
props组件属性any
key搜索参数键名string
tooltip提示信息string
order排序number0
span栅栏占据的列数number6
offset栅栏左侧偏移格数number0
defaultValue默认值string | number | boolean | any[] | Ref<any>
render自定义渲染(scope: SearchRenderScope) => VNode

Events

事件名说明类型
search点击搜索按钮时触发() => void
reset点击重置按钮时触发() => void
dragSort拖拽排序时触发(args: { newIndex?: number; oldIndex?: number }) => void

Slots

插槽名说明作用域
tableHeader表格头部左侧内容{ selectedList, selectedListIds, isSelected }
toolButton工具栏按钮
expand展开行内容{ row, $index }
empty空数据时的内容

方法

方法名说明类型
getTableList获取表格数据() => void
search执行搜索() => void
reset重置搜索() => void
handleSizeChange改变分页大小(size: number) => void
handleCurrentChange改变当前页(page: number) => void
clearSelection清空选择() => void
toggleSearchVisibility切换搜索栏显示(value: boolean) => void

属性

属性名说明类型
element表格实例Ref<ElTable>
tableData表格数据Ref<any[]>
radio单选值Ref<string>
pageable分页信息Ref<Pageable>
searchParam搜索参数Ref<{ [key: string]: any }>
searchInitParam搜索初始参数Ref<{ [key: string]: any }>
isSelected是否选中Ref<boolean>
selectedList选中列表Ref<any[]>
selectedListIds选中列表 IDRef<any[]>
isShowSearch是否显示搜索栏Ref<boolean>
enumMap枚举映射Ref<Map<string, EnumProps[]>>