branchErp/src/components/x-n-data-table
2025-09-18 14:14:05 +08:00
..
index.vue first commit 2025-09-18 14:14:05 +08:00
README.md first commit 2025-09-18 14:14:05 +08:00

@x-n-data-table

基于 Naive UI 的 n-data-table 组件封装,增加了拖拽排序功能和灵活的插槽支持。

功能特性

  • 支持所有 n-data-table 的原有功能
  • 支持列拖拽排序
  • 支持拖拽手柄模式
  • 支持每列的自定义插槽
  • 支持列标题的自定义插槽
  • 支持自定义拖拽列渲染

安装

# 项目中已经包含此组件,无需额外安装

插槽功能

💡 这是对原生 n-data-table 的重要增强:支持为每一列配置具名插槽

列内容插槽

使用列的 key 作为插槽名称:

<template>
  <x-n-data-table :columns="columns" :data="data">
    <!-- 使用 name 列的插槽 -->
    <template #name="{ row, index }">
      <n-tag>{{ row.name }}</n-tag>
    </template>
    
    <!-- 使用 status 列的插槽 -->
    <template #status="{ row }">
      <n-badge :status="row.status" />
    </template>
  </x-n-data-table>
</template>

列标题插槽

使用 {key}_title 作为插槽名称:

<template>
  <x-n-data-table :columns="columns" :data="data">
    <!-- 自定义 name 列的标题 -->
    <template #name_title>
      <n-space>
        <n-icon><user /></n-icon>
        <span>用户名</span>
      </n-space>
    </template>
  </x-n-data-table>
</template>

使用方法

<template>
  <x-n-data-table
    :columns="columns"
    :data="data"
  >
    <!-- 自定义拖拽列的内容 -->
    <template #sort="{ row, index }">
      <n-space>
        <n-icon>⋮⋮</n-icon>
        <span>{{ index + 1 }}</span>
      </n-space>
    </template>

    <!-- 自定义名称列的标题 -->
    <template #name_title>
      <n-space>
        <n-icon><list /></n-icon>
        <span>项目名称</span>
      </n-space>
    </template>

    <!-- 自定义名称列的内容 -->
    <template #name="{ row }">
      <n-ellipsis>
        {{ row.name }}
      </n-ellipsis>
    </template>
  </x-n-data-table>
</template>

<script setup lang="ts">
import { ref } from 'vue'

const data = ref([
  { id: 1, name: '项目1' },
  { id: 2, name: '项目2' },
  { id: 3, name: '项目3' }
])

const columns = [
  {
    key: 'sort',
    title: '排序',
    type: 'drag',
    handle: true,
    onDragEnd: ({ oldIndex, newIndex }) => {
      const newData = [...data.value]
      const [removed] = newData.splice(oldIndex, 1)
      newData.splice(newIndex, 0, removed)
      data.value = newData
    }
  },
  {
    key: 'name',
    title: '名称'
  }
]
</script>

API

Props

属性 类型 默认值 说明
columns Array<Column | DragColumn> [] 列配置,支持拖拽列
data Array<object> [] 数据源
align string 'center' 对齐方式

其他属性与 n-data-table 保持一致。

Slots

插槽名 参数 说明
{key} { row, index } 列内容的自定义渲染key 为列的 key
{key}_title - 列标题的自定义渲染key 为列的 key

DragColumn 配置

属性 类型 默认值 说明
type 'drag' - 指定为拖拽列
handle boolean false 是否只能通过手柄拖拽
onDragEnd (event: DragSortEvent) => void - 拖拽结束回调

DragSortEvent

属性 类型 说明
oldIndex number 拖拽前的索引
newIndex number 拖拽后的索引

方法

组件暴露了以下方法:

方法名 参数 说明
clearFilters - 清除过滤条件
clearSorter - 清除排序条件
filter (filters: any) 设置过滤条件
page (page: number) 跳转到指定页
sort (columnKey: string, order: 'ascend' | 'descend' | false) 设置排序

注意事项

  1. 拖拽列的 type 必须设置为 'drag'
  2. 拖拽功能需要配置 onDragEnd 回调来更新数据
  3. 建议将拖拽列放在表格的第一列
  4. 如果需要禁用整行拖拽,请设置 handle: true
  5. 插槽名称必须与列的 key 对应
  6. 标题插槽需要加上 _title 后缀

示例

完整示例

<template>
  <x-n-data-table
    :columns="columns"
    :data="data"
  >
    <!-- 拖拽列自定义渲染 -->
    <template #sort="{ index }">
      <n-space>
        <n-icon>⋮⋮</n-icon>
        <span>{{ index + 1 }}</span>
      </n-space>
    </template>

    <!-- 名称列标题自定义渲染 -->
    <template #name_title>
      <n-space>
        <n-icon><list /></n-icon>
        <span>项目名称</span>
      </n-space>
    </template>

    <!-- 名称列内容自定义渲染 -->
    <template #name="{ row }">
      <n-ellipsis>
        {{ row.name }}
      </n-ellipsis>
    </template>

    <!-- 状态列自定义渲染 -->
    <template #status="{ row }">
      <n-tag :type="row.status">
        {{ row.statusText }}
      </n-tag>
    </template>
  </x-n-data-table>
</template>

<script setup lang="ts">
const data = ref([
  { id: 1, name: '项目1', status: 'success', statusText: '正常' },
  { id: 2, name: '项目2', status: 'warning', statusText: '警告' }
])

const columns = [
  {
    key: 'sort',
    title: '排序',
    type: 'drag',
    handle: true,
    onDragEnd: ({ oldIndex, newIndex }) => {
      const newData = [...data.value]
      const [removed] = newData.splice(oldIndex, 1)
      newData.splice(newIndex, 0, removed)
      data.value = newData
    }
  },
  {
    key: 'name',
    title: '名称'
  },
  {
    key: 'status',
    title: '状态'
  }
]
</script>