Skip to content

DataGrid 数据表格

用于展示多条结构类似的数据,可对数据进行排序、筛选、对比或其他自定义操作。

基础用法

基础的表格展示用法。

<template>
  <div class="demo-container">
    <MDataGrid
      :columns="columns"
      :data-source="dataSource"
      height="400px"
    />
  </div>
</template>

<script setup lang="ts">
import { MDataGrid } from 'moonwind-ui'
import type { DataGridColumn } from 'moonwind-ui'

interface User {
  id: number
  name: string
  email: string
  age: number
  department: string
  status: string
}

const columns: DataGridColumn[] = [
  { field: 'id', headerName: 'ID', width: 80 },
  { field: 'name', headerName: '姓名', width: 120 },
  { field: 'email', headerName: '邮箱', width: 200 },
  { field: 'age', headerName: '年龄', width: 80 },
  { field: 'department', headerName: '部门', width: 120 },
  { field: 'status', headerName: '状态', width: 100 }
]

const dataSource: User[] = [
  { id: 1, name: '张三', email: 'zhangsan@example.com', age: 28, department: '技术部', status: '在职' },
  { id: 2, name: '李四', email: 'lisi@example.com', age: 32, department: '产品部', status: '在职' },
  { id: 3, name: '王五', email: 'wangwu@example.com', age: 25, department: '设计部', status: '在职' },
  { id: 4, name: '赵六', email: 'zhaoliu@example.com', age: 30, department: '市场部', status: '离职' },
  { id: 5, name: '钱七', email: 'qianqi@example.com', age: 27, department: '技术部', status: '在职' },
  { id: 6, name: '孙八', email: 'sunba@example.com', age: 35, department: '人事部', status: '在职' },
  { id: 7, name: '周九', email: 'zhoujiu@example.com', age: 29, department: '财务部', status: '在职' },
  { id: 8, name: '吴十', email: 'wushi@example.com', age: 26, department: '技术部', status: '在职' }
]
</script>

<style scoped>
.demo-container {
  margin: 20px 0;
  border: 1px solid #e1e5e9;
  border-radius: 6px;
  padding: 16px;
  background: #fff;
}

.hk-data-grid {
  border: 1px solid #e8e8e8;
  border-radius: 4px;
}
</style>

分页

支持分页功能。

<template>
  <div class="demo-container">
    <MDataGrid
      :columns="columns"
      :data-source="dataSource"
      :pagination="pagination"
      :toolbar="{ visible: true, showQuickFilter: true, showReset: true }"
      height="500px"
    />
  </div>
</template>

<script setup lang="ts">
import { MDataGrid } from 'moonwind-ui'
import type { DataGridColumn, PaginationConfig } from 'moonwind-ui'

interface User {
  id: number
  name: string
  email: string
  age: number
  department: string
  status: string
  joinDate: string
}

const columns: DataGridColumn<User>[] = [
  { field: 'id', headerName: 'ID', width: 80 },
  { field: 'name', headerName: '姓名', width: 120 },
  { field: 'email', headerName: '邮箱', width: 200 },
  { field: 'age', headerName: '年龄', width: 80 },
  { field: 'department', headerName: '部门', width: 120 },
  { field: 'status', headerName: '状态', width: 100 },
  { field: 'joinDate', headerName: '入职日期', width: 120 }
]

// 生成更多数据用于分页演示
const generateData = (): User[] => {
  const departments = ['技术部', '产品部', '设计部', '市场部', '人事部', '财务部']
  const statuses = ['在职', '离职', '试用期']
  const data: User[] = []
  
  for (let i = 1; i <= 50; i++) {
    data.push({
      id: i,
      name: `用户${i}`,
      email: `user${i}@example.com`,
      age: 20 + Math.floor(Math.random() * 20),
      department: departments[Math.floor(Math.random() * departments.length)],
      status: statuses[Math.floor(Math.random() * statuses.length)],
      joinDate: `2023-${String(Math.floor(Math.random() * 12) + 1).padStart(2, '0')}-${String(Math.floor(Math.random() * 28) + 1).padStart(2, '0')}`
    })
  }
  
  return data
}

const dataSource = generateData()

const pagination: PaginationConfig = {
  current: 1,
  pageSize: 10,
  total: dataSource.length,
  showSizeChanger: true,
  showQuickJumper: true,
  showTotal: true,
  pageSizeOptions: ['10', '20', '50', '100']
}
</script>

<style scoped>
.demo-container {
  margin: 20px 0;
  border: 1px solid #e1e5e9;
  border-radius: 6px;
  padding: 16px;
  background: #fff;
}

.hk-data-grid {
  border: 1px solid #e8e8e8;
  border-radius: 4px;
}
</style>

排序

对表格进行排序,可快速查找或对比数据。

<template>
  <MDataGrid
    :columns="columns"
    :data-source="dataSource"
    height="500px"
  />
</template>

<script setup lang="ts">
import { MDataGrid } from 'moonwind-ui'
import type { DataGridColumn } from 'moonwind-ui'

interface User {
  id: number
  name: string
  email: string
  age: number
  salary: number
  department: string
}

const columns: DataGridColumn[] = [
  { field: 'id', headerName: 'ID', width: 80, sortable: true },
  { field: 'name', headerName: '姓名', width: 120, sortable: true },
  { field: 'email', headerName: '邮箱', width: 200 },
  { field: 'age', headerName: '年龄', width: 80, sortable: true },
  { 
    field: 'salary', 
    headerName: '薪资', 
    width: 120, 
    sortable: true,
    cellRenderer: (params: any) => {
      return `¥${params.value.toLocaleString()}`
    }
  },
  { field: 'department', headerName: '部门', width: 120, sortable: true }
]

const dataSource: User[] = [
  {
    id: 1,
    name: '张三',
    email: 'zhangsan@example.com',
    age: 25,
    salary: 8000,
    department: '技术部'
  },
  {
    id: 2,
    name: '李四',
    email: 'lisi@example.com',
    age: 30,
    salary: 12000,
    department: '产品部'      
  },
  {
    id: 3,
    name: '王五',
    email: 'wangwu@example.com',
    age: 28,
    salary: 10000,
    department: '设计部'
  },
  {
    id: 4,
    name: '赵六',
    email: 'zhaoliu@example.com',
    age: 32,
    salary: 15000,
    department: '技术部'
  },
  {
    id: 5,
    name: '钱七',
    email: 'qianqi@example.com',
    age: 27,
    salary: 9000,
    department: '运营部'
  },
  {
    id: 6,
    name: '孙八',
    email: 'sunba@example.com',
    age: 35,
    salary: 18000,
    department: '产品部'
  },
  {
    id: 7,
    name: '周九',
    email: 'zhoujiu@example.com',
    age: 26,
    salary: 7500,
    department: '设计部'
  },
  {
    id: 8,
    name: '吴十',
    email: 'wushi@example.com',
    age: 29,
    salary: 11000,
    department: '技术部'
  }
]
</script>

<style scoped>
.hk-data-grid {
  border: 1px solid #e8e8e8;
  border-radius: 4px;
}
</style>

筛选

对表格进行筛选,可快速查找数据。

<template>
  <MDataGrid
    :columns="columns"
    :data-source="dataSource"
    height="500px"
  />
</template>

<script setup lang="ts">
import { MDataGrid } from 'moonwind-ui'
import type { DataGridColumn } from 'moonwind-ui'

interface User {
  id: number
  name: string
  email: string
  age: number
  department: string
  status: string
}

const columns: DataGridColumn[] = [
  { field: 'id', headerName: 'ID', width: 80 },
  { field: 'name', headerName: '姓名', width: 120, filter: true },
  { field: 'email', headerName: '邮箱', width: 200, filter: true },
  { field: 'age', headerName: '年龄', width: 80, filter: 'agNumberColumnFilter' },
  { 
    field: 'department', 
    headerName: '部门', 
    width: 120, 
    filter: 'agTextColumnFilter'
  },
  { 
    field: 'status', 
    headerName: '状态', 
    width: 100, 
    filter: 'agTextColumnFilter',
    cellRenderer: (params: any) => {
      const status = params.value
      const colorMap: Record<string, string> = {
        '在职': '#52c41a',
        '离职': '#ff4d4f',
        '试用期': '#faad14'
      }
      const color = colorMap[status] || '#666'
      return `<span style="color: ${color}; font-weight: bold;">${status}</span>`
    }
  }
]

const dataSource: User[] = [
  {
    id: 1,
    name: '张三',
    email: 'zhangsan@example.com',
    age: 25,
    department: '技术部',
    status: '在职'
  },
  {
    id: 2,
    name: '李四',
    email: 'lisi@example.com',
    age: 30,
    department: '产品部',
    status: '在职'
  },
  {
    id: 3,
    name: '王五',
    email: 'wangwu@example.com',
    age: 28,
    department: '设计部',
    status: '试用期'
  },
  {
    id: 4,
    name: '赵六',
    email: 'zhaoliu@example.com',
    age: 32,
    department: '技术部',
    status: '在职'
  },
  {
    id: 5,
    name: '钱七',
    email: 'qianqi@example.com',
    age: 27,
    department: '运营部',
    status: '离职'
  },
  {
    id: 6,
    name: '孙八',
    email: 'sunba@example.com',
    age: 35,
    department: '产品部',  
    status: '在职'
  },
  {
    id: 7,
    name: '周九',
    email: 'zhoujiu@example.com',
    age: 26,
    department: '设计部',
    status: '试用期'
  },
  {
    id: 8,
    name: '吴十',
    email: 'wushi@example.com',
    age: 29,
    department: '技术部',
    status: '在职'
  },
  {
    id: 9,
    name: '郑十一',
    email: 'zhengshiyi@example.com',
    age: 31,
    department: '运营部',   
    status: '在职'
  },
  {
    id: 10,
    name: '王十二',
    email: 'wangshier@example.com',
    age: 24,
    department: '设计部',
    status: '试用期'
  }
]
</script>

<style scoped>
.hk-data-grid {
  border: 1px solid #e8e8e8;
  border-radius: 4px;
}
</style>

自定义列

自定义列的显示内容。

<template>
  <MDataGrid
    :columns="columns"
    :data-source="dataSource"
    height="500px"
  />
</template>

<script setup lang="ts">
import { MDataGrid } from 'moonwind-ui'
import type { DataGridColumn } from 'moonwind-ui'

interface User {
  id: number
  name: string
  email: string
  age: number
  status: 'active' | 'inactive'
  avatar: string
}

const columns: DataGridColumn[] = [
  { field: 'id', headerName: 'ID', width: 80 },
  { 
    field: 'avatar', 
    headerName: '头像', 
    width: 100,
    cellRenderer: (params: any) => {
      return `<img src="${params.value}" alt="头像" style="width: 32px; height: 32px; border-radius: 50%;" />`
    }
  },
  { field: 'name', headerName: '姓名', width: 120 },
  { field: 'email', headerName: '邮箱', width: 200 },
  { field: 'age', headerName: '年龄', width: 80 },
  { 
    field: 'status', 
    headerName: '状态', 
    width: 100,
    cellRenderer: (params: any) => {
      const status = params.value
      const color = status === 'active' ? '#52c41a' : '#ff4d4f'
      const text = status === 'active' ? '活跃' : '非活跃'
      return `<span style="color: ${color}; font-weight: bold;">${text}</span>`
    }
  }
]

const dataSource: User[] = [
  {
    id: 1,
    name: '张三',
    email: 'zhangsan@example.com',
    age: 25,
    status: 'active',
    avatar: 'https://api.dicebear.com/7.x/avataaars/svg?seed=1'
  },
  {
    id: 2,
    name: '李四',
    email: 'lisi@example.com',
    age: 30,
    status: 'inactive',
    avatar: 'https://api.dicebear.com/7.x/avataaars/svg?seed=2'
  },
  {
    id: 3,
    name: '王五',
    email: 'wangwu@example.com',
    age: 28,
    status: 'active',
    avatar: 'https://api.dicebear.com/7.x/avataaars/svg?seed=3'
  },
  {
    id: 4,
    name: '赵六',
    email: 'zhaoliu@example.com',
    age: 32,
    status: 'active',
    avatar: 'https://api.dicebear.com/7.x/avataaars/svg?seed=4'
  },
  {
    id: 5,
    name: '钱七',
    email: 'qianqi@example.com',
    age: 27,
    status: 'inactive',
    avatar: 'https://api.dicebear.com/7.x/avataaars/svg?seed=5'
  }
]
</script>

<style scoped>
.hk-data-grid {
  border: 1px solid #e8e8e8;
  border-radius: 4px;
}
</style>

工具栏

显示工具栏,提供额外的操作功能。

<template>
  <div class="demo-container">
    <MDataGrid
      :columns="columns"
      :data-source="dataSource"
      height="400px"
      :toolbar="{
        showQuickFilter: true,
        showReset: true,
        showColumnToggle: true,
        placement: 'top'
      }"
    />
  </div>
</template>

<script setup lang="ts">
import { MDataGrid } from 'moonwind-ui'
import type { DataGridColumn, ToolbarConfig } from 'moonwind-ui'

interface User {
  id: number
  name: string
  email: string
  age: number
  department: string
  status: string
  salary: number
}

const columns: DataGridColumn[] = [
  { field: 'id', headerName: 'ID', width: 80, sortable: true },
  { field: 'name', headerName: '姓名', width: 120, sortable: true },
  { field: 'email', headerName: '邮箱', width: 200 },
  { field: 'age', headerName: '年龄', width: 80, sortable: true },
  { field: 'department', headerName: '部门', width: 120, filter: true },
  { field: 'status', headerName: '状态', width: 100, filter: true },
  { field: 'salary', headerName: '薪资', width: 120, sortable: true }
]

const dataSource: User[] = [
  { id: 1, name: '张三', email: 'zhangsan@example.com', age: 28, department: '技术部', status: '在职', salary: 15000 },
  { id: 2, name: '李四', email: 'lisi@example.com', age: 32, department: '产品部', status: '在职', salary: 18000 },
  { id: 3, name: '王五', email: 'wangwu@example.com', age: 25, department: '设计部', status: '在职', salary: 12000 },
  { id: 4, name: '赵六', email: 'zhaoliu@example.com', age: 30, department: '市场部', status: '离职', salary: 14000 },
  { id: 5, name: '钱七', email: 'qianqi@example.com', age: 27, department: '技术部', status: '在职', salary: 16000 },
  { id: 6, name: '孙八', email: 'sunba@example.com', age: 35, department: '人事部', status: '在职', salary: 13000 },
  { id: 7, name: '周九', email: 'zhoujiu@example.com', age: 29, department: '财务部', status: '在职', salary: 17000 },
  { id: 8, name: '吴十', email: 'wushi@example.com', age: 26, department: '技术部', status: '试用期', salary: 11000 },
  { id: 9, name: '郑十一', email: 'zheng11@example.com', age: 31, department: '产品部', status: '在职', salary: 19000 },
  { id: 10, name: '王十二', email: 'wang12@example.com', age: 24, department: '设计部', status: '试用期', salary: 10000 }
]
</script>

<style scoped>
.demo-container {
  margin: 20px 0;
  border: 1px solid #e1e5e9;
  border-radius: 6px;
  padding: 16px;
  background: #fff;
}

.hk-data-grid {
  border: 1px solid #e8e8e8;
  border-radius: 4px;
}
</style>

行选择

支持行选择功能。

<template>
  <div class="demo-container">
    <div class="selection-info">
      <p>已选择 {{ selectedKeys.length }} 行数</p>
      <div v-if="selectedKeys.length > 0" class="selected-items">
        <strong>选中的用户:</strong>
        <span v-for="(key, index) in selectedKeys" :key="key">
          {{ getSelectedUserName(key) }}{{ index < selectedKeys.length - 1 ? ', ' : '' }}
        </span>
      </div>
    </div>
    
    <MDataGrid
      :columns="columns"
      :data-source="dataSource"
      :row-selection="rowSelection"
      :toolbar="{ visible: true, showColumnToggle: true, showReset: true }"
      height="400px"
    />
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { MDataGrid } from 'moonwind-ui'
import type { DataGridColumn, RowSelectionConfig } from 'moonwind-ui'

interface User {
  id: number
  name: string
  email: string
  age: number
  department: string
  status: string
}

const columns: DataGridColumn<User>[] = [
  { field: 'id', headerName: 'ID', width: 80 },
  { field: 'name', headerName: '姓名', width: 120 },
  { field: 'email', headerName: '邮箱', width: 200 },
  { field: 'age', headerName: '年龄', width: 80 },
  { field: 'department', headerName: '部门', width: 120 },
  { field: 'status', headerName: '状态', width: 100 }
]

const dataSource: User[] = [
  { id: 1, name: '张三', email: 'zhangsan@example.com', age: 28, department: '技术部', status: '在职' },
  { id: 2, name: '李四', email: 'lisi@example.com', age: 32, department: '产品部', status: '在职' },
  { id: 3, name: '王五', email: 'wangwu@example.com', age: 25, department: '设计部', status: '在职' },
  { id: 4, name: '赵六', email: 'zhaoliu@example.com', age: 30, department: '市场部', status: '离职' },
  { id: 5, name: '钱七', email: 'qianqi@example.com', age: 27, department: '技术部', status: '在职' },
  { id: 6, name: '孙八', email: 'sunba@example.com', age: 35, department: '人事部', status: '在职' },
  { id: 7, name: '周九', email: 'zhoujiu@example.com', age: 29, department: '财务部', status: '在职' },
  { id: 8, name: '吴十', email: 'wushi@example.com', age: 26, department: '技术部', status: '在职' }
]

const selectedKeys = ref<number[]>([])

const rowSelection: RowSelectionConfig<User> = {
  type: 'checkbox',
  selectedKeys: selectedKeys.value,
  onChange: (keys: number[], rows: User[]) => {
    selectedKeys.value = keys
    console.log('选中的行:', rows)
  }
}

const getSelectedUserName = (id: number): string => {
  const user = dataSource.find(u => u.id === id)
  return user ? user.name : ''
}
</script>

<style scoped>
.demo-container {
  margin: 20px 0;
  border: 1px solid #e1e5e9;
  border-radius: 6px;
  padding: 20px;
}

.selection-info {
  margin-bottom: 16px;
  padding: 12px;
  background-color: #f6f8fa;
  border-radius: 4px;
  border: 1px solid #e1e5e9;
}

.selection-info p {
  margin: 0 0 8px 0;
  font-weight: 500;
  color: #24292f;
}

.selected-items {
  color: #656d76;
  font-size: 14px;
}

.selected-items strong {
  color: #24292f;
}
</style>

远程数据

通过 fetch 属性配置远程数据获取。

<template>
  <MDataGrid
    :columns="columns"
    :fetch="fetchData"
    :pagination="pagination"
    height="500px"
  />
</template>

<script setup lang="ts">
import { MDataGrid } from 'moonwind-ui'
import type { DataGridColumn } from 'moonwind-ui'

interface User {
  id: number
  name: string
  email: string
  age: number
  department: string
}

const columns: DataGridColumn[] = [
  { field: 'id', headerName: 'ID', width: 80 },
  { field: 'name', headerName: '姓名', width: 120 },
  { field: 'email', headerName: '邮箱', width: 200 },
  { field: 'age', headerName: '年龄', width: 80 },
  { field: 'department', headerName: '部门', width: 120 }
]

const pagination = {
  current: 1,
  pageSize: 10,
  total: 0,
  showSizeChanger: true,
  showQuickJumper: true,
  showTotal: true
}

const fetchData = async (params: any) => {
  // 模拟 API 请求
  await new Promise(resolve => setTimeout(resolve, 1000))
  
  const { current = 1, pageSize = 10 } = params
  const total = 100
  const start = (current - 1) * pageSize
  
  const data: User[] = Array.from({ length: pageSize }, (_, index) => ({
    id: start + index + 1,
    name: `用户${start + index + 1}`,
    email: `user${start + index + 1}@example.com`,
    age: 20 + (start + index) % 40,
    department: ['技术部', '产品部', '设计部', '运营部'][index % 4]
  }))
  
  return {
    data,
    total
  }
}
</script>

<style scoped>
.hk-data-grid {
  border: 1px solid #e8e8e8;
  border-radius: 4px;
}
</style>

API

Props

属性名说明类型默认值
columns列配置DataGridColumn[][]
dataSource数据源any[][]
fetch远程数据获取函数Function
pagination分页配置PaginationConfig
rowSelection行选择配置RowSelectionConfig
toolbar工具栏配置ToolbarConfig
loading加载状态booleanfalse
height表格高度string / number

Events

事件名说明回调参数
row-click行点击事件(row: any)
selection-change选择项发生变化时触发(selection: any[])
page-change页码改变时触发(page: number)
page-size-change每页条数改变时触发(pageSize: number)

Methods

方法名说明参数
refresh刷新表格数据
clearSelection清空选择
getSelectedRows获取选中的行数据

DataGridColumn

属性名说明类型默认值
field列字段名string
headerName列标题string
width列宽度number
sortable是否可排序booleanfalse
filter是否可筛选booleanfalse
hide是否隐藏booleanfalse