Vxe UI vue vxe-table 常用功能使用分享

Vxe UI vue vxe-table 常用功能使用分享

表格需求

如果你需要的是一个能够渲染简单场景的表格,那么使用主流 UI 库就够了,例如element ui自带的表格等。
如果你需要是一个能同时满足简单场景以及各类复杂场景、大数量的全功能表格,那么推荐 vxe-table 就是首选。无论是基础表格还是大数量表格,功能强大和渲染性能也很不错。

介绍

Vxe UI 是 vxe-table 配套的组件库,如果表格中需要用到一些组件,比如:弹框、抽屉、页签等,可以选择第三方的组件库,也可以使用配置的 UI 库,安装后就能直接使用。

// ...
import VxeUI from 'vxe-pc-ui'
import 'vxe-pc-ui/lib/style.css'

import VxeUITable from 'vxe-table'
import 'vxe-table/lib/style.css'

// ...
createApp(App).use(VxeUI).use(VxeUITable).mount('#app')

组件 table 和 grid 哪个好用

无需考虑,直接选 vxe-grid,vxe-grid 是 vxe-table 的配置式版本,table 能做的 grid 也能做,table不支持的,grid 也能支持。

单选

在这里插入图片描述

<template>
  <div>
    <vxe-grid v-bind="gridOptions"></vxe-grid>
  </div>
</template>

<script setup>
import { reactive } from 'vue'
const gridOptions = reactive({
  border: true,
  height: 300,
  rowConfig: {
    isHover: true
  },
  radioConfig: {
    labelField: 'name',
    highlight: true
  },
  columns: [
    { type: 'radio', title: 'Name', width: 300 },
    { field: 'id', title: 'ID' },
    { field: 'age', title: 'Age' },
    { field: 'address', title: 'Address', showOverflow: true }
  ],
  data: [
    { id: 10001, name: 'Test1', role: 'Develop', sex: 'Man', age: 28, address: 'test abc' },
    { id: 10002, name: 'Test2', role: 'Test', sex: 'Women', age: 22, address: 'Guangzhou' },
    { id: 10003, name: 'Test3', role: 'PM', sex: 'Man', age: 32, address: 'Shanghai' },
    { id: 10004, name: 'Test4', role: 'Designer', sex: 'Women', age: 23, address: 'test abc' },
    { id: 10005, name: 'Test5', role: 'Develop', sex: 'Women', age: 30, address: 'Shanghai' }
  ]
})
</script>

多选

在这里插入图片描述

<template>
  <div>
    <vxe-grid v-bind="gridOptions"></vxe-grid>
  </div>
</template>

<script setup>
import { reactive } from 'vue'
const gridOptions = reactive({
  border: true,
  height: 500,
  rowConfig: {
    isHover: true
  },
  checkboxConfig: {
    labelField: 'name',
    highlight: true
  },
  columns: [
    { type: 'checkbox', title: 'Name', width: 300 },
    { field: 'id', title: 'ID' },
    { field: 'age', title: 'Age' },
    { field: 'address', title: 'Address', showOverflow: true }
  ],
  data: [
    { id: 10001, name: 'Test1', role: 'Develop', sex: 'Man', age: 28, address: 'test abc' },
    { id: 10002, name: 'Test2', role: 'Test', sex: 'Women', age: 22, address: 'Guangzhou' },
    { id: 10003, name: 'Test3', role: 'PM', sex: 'Man', age: 32, address: 'Shanghai' },
    { id: 10004, name: 'Test4', role: 'Designer', sex: 'Women', age: 23, address: 'test abc' },
    { id: 10005, name: 'Test5', role: 'Develop', sex: 'Women', age: 30, address: 'Shanghai' }
  ]
})
</script>

表位合计

在这里插入图片描述

<template>
  <div>
    <vxe-grid v-bind="gridOptions"></vxe-grid>
  </div>
</template>

<script setup>
import { reactive } from 'vue'
const gridOptions = reactive({
  border: true,
  showFooter: true,
  height: 300,
  columns: [
    { field: 'seq', type: 'seq', width: 70 },
    { field: 'name', title: 'Name' },
    { field: 'sex', title: 'Sex' },
    {
      field: 'num',
      title: 'Num',
      footerFormatter ({ itemValue }) {
        return `${itemValue}`
      }
    },
    { field: 'address', title: 'Address', showOverflow: true }
  ],
  data: [
    { id: '10001', name: 'Test1', role: 'Develop', sex: 'Man', num: '28', address: 'test abc' },
    { id: '10002', name: 'Test2', role: 'Test', sex: 'Women', num: '22', address: 'Guangzhou' },
    { id: '10003', name: 'Test3', role: 'PM', sex: 'Man', num: '32', address: 'Shanghai' },
    { id: '10004', name: 'Test4', role: 'Designer', sex: 'Women', num: '24', address: 'Shanghai' },
    { id: '10005', name: 'Test5', role: 'Develop', sex: 'Man', num: '42', address: 'Guangzhou' },
    { id: '10006', name: 'Test6', role: 'Test', sex: 'Women', num: '39', address: 'Shanghai' },
    { id: '10007', name: 'Test7', role: 'Develop', sex: 'Man', num: '46', address: 'Shanghai' },
    { id: '10008', name: 'Test8', role: 'PM', sex: 'Women', num: '49', address: 'Guangzhou' }
  ],
  footerData: [
    { seq: '合计', num: '282' }
  ]
})
</script>

右键菜单

支持表头、单元格、表尾等各种右键菜单的配置,功能太多,这里只简单说明一下基本使用
在这里插入图片描述

<template>
  <div>
    <vxe-grid ref="gridRef" v-bind="gridOptions" v-on="gridEvents"></vxe-grid>
  </div>
</template>

<script setup>
import { ref, reactive } from 'vue'
import { VxeUI } from 'vxe-table'
const gridRef = ref()
const gridOptions = reactive({
  border: true,
  showFooter: true,
  rowConfig: {
    isCurrent: true
  },
  columnConfig: {
    resizable: true
  },
  columns: [
    { field: 'checkbox', type: 'checkbox', width: 50 },
    { type: 'seq', width: 70 },
    { field: 'name', title: 'Name' },
    { field: 'nickname', title: 'Nickname' },
    { field: 'age', title: 'Age' },
    { field: 'role', title: 'Role' },
    { field: 'address', title: 'Address', showOverflow: true }
  ],
  data: [
    { id: 10001, name: 'Test1', nickname: 'T1', role: 'Develop', sex: 'Man', age: 28, address: 'Shenzhen' },
    { id: 10002, name: 'Test2', nickname: 'T2', role: 'Test', sex: 'Women', age: 22, address: 'Guangzhou' },
    { id: 10003, name: 'Test3', nickname: 'T3', role: 'PM', sex: 'Man', age: 32, address: 'Shanghai' },
    { id: 10004, name: 'Test4', nickname: 'T4', role: 'Designer', sex: 'Women', age: 23, address: 'Shenzhen' },
    { id: 10005, name: 'Test5', nickname: 'T5', role: 'Develop', sex: 'Women', age: 30, address: 'Shanghai' }
  ],
  menuConfig: {
    header: {
      options: [
        [
          { code: 'exportAll', name: '导出所有.csv', prefixIcon: 'vxe-icon-download', visible: true, disabled: false }
        ]
      ]
    },
    body: {
      options: [
        [
          { code: 'copy', name: '复制内容', prefixIcon: 'vxe-icon-copy', visible: true, disabled: false },
          { code: 'clear', name: '清除内容', visible: true, disabled: false },
          { code: 'reload', name: '刷新表格', visible: true, disabled: false }
        ],
        [
          { code: 'myPrint', name: '打印', prefixIcon: 'vxe-icon-print', visible: true, disabled: false },
          { code: 'myExport', name: '导出.csv', prefixIcon: 'vxe-icon-download', visible: true, disabled: false }
        ]
      ]
    },
    footer: {
      options: [
        [
          { code: 'exportAll', name: '导出所有.csv', prefixIcon: 'vxe-icon-download', visible: true, disabled: false }
        ]
      ]
    }
  },
  footerData: [
    { checkbox: '合计', age: 135 }
  ]
})
const gridEvents = {
  cellMenu ({ row }) {
    const $grid = gridRef.value
    if ($grid) {
      $grid.setCurrentRow(row)
    }
  },
  menuClick ({ menu, row, column }) {
    const $grid = gridRef.value
    if ($grid) {
      switch (menu.code) {
        case 'copy':
          if (row && column) {
            if (VxeUI.clipboard.copy(row[column.field])) {
              VxeUI.modal.message({ content: '已复制到剪贴板!', status: 'success' })
            }
          }
          break
        case 'clear':
          $grid.clearData(row, column.field)
          break
        case 'myPrint':
          $grid.print()
          break
        case 'myExport':
          $grid.exportData()
          break
      }
    }
  }
}
</script>

个性化列设置

自定义列功能支持本地 localStorage 自动保存,服务端调用接口保存与恢复状态
在这里插入图片描述

<template>
  <div>
    <vxe-grid v-bind="gridOptions"></vxe-grid>
  </div>
</template>

<script setup>
import { reactive } from 'vue'
const gridOptions = reactive({
  border: true,
  id: 'myCustomStorage',
  toolbarConfig: {
    custom: true
  },
  customConfig: {
    storage: true
  },
  columns: [
    { type: 'seq', width: 70 },
    { field: 'name', title: 'Name' },
    { field: 'role', title: 'role' },
    { field: 'sex', title: 'Sex' },
    { field: 'age', title: 'Age' },
    { field: 'address', title: 'address' }
  ],
  data: [
    { id: 10001, name: 'Test1', role: 'Develop', sex: 'Man', age: 28, address: 'test abc' },
    { id: 10002, name: 'Test2', role: 'Test', sex: 'Women', age: 22, address: 'Guangzhou' },
    { id: 10003, name: 'Test3', role: 'PM', sex: 'Man', age: 32, address: 'Shanghai' },
    { id: 10004, name: 'Test4', role: 'Designer', sex: 'Women', age: 24, address: 'Shanghai' }
  ]
})
</script>

树表格

树表格支持多种结构,平级数组还是带父子层级的结构都能渲染,功能太多,这里只说其中一种方式
在这里插入图片描述

<template>
  <div>
    <vxe-grid v-bind="gridOptions"></vxe-grid>
  </div>
</template>

<script setup>
import { reactive } from 'vue'
const gridOptions = reactive({
  border: true,
  treeConfig: {
    transform: true,
    rowField: 'id',
    parentField: 'parentId'
  },
  columns: [
    { type: 'seq', width: 70 },
    { field: 'name', title: 'Name', minWidth: 300, treeNode: true },
    { field: 'size', title: 'Size' },
    { field: 'type', title: 'Type' },
    { field: 'date', title: 'Date' }
  ],
  data: [
    { id: 10000, parentId: null, name: 'Test1', type: 'mp3', size: 1024, date: '2020-08-01' },
    { id: 10050, parentId: null, name: 'Test2', type: 'mp4', size: 0, date: '2021-04-01' },
    { id: 24300, parentId: 10050, name: 'Test3', type: 'avi', size: 1024, date: '2020-03-01' },
    { id: 20045, parentId: 24300, name: 'Test4', type: 'html', size: 600, date: '2021-04-01' },
    { id: 10053, parentId: 24300, name: 'Test5', type: 'avi', size: 0, date: '2021-04-01' },
    { id: 24330, parentId: 10053, name: 'Test6', type: 'txt', size: 25, date: '2021-10-01' },
    { id: 21011, parentId: 10053, name: 'Test7', type: 'pdf', size: 512, date: '2020-01-01' },
    { id: 22200, parentId: 10053, name: 'Test8', type: 'js', size: 1024, date: '2021-06-01' },
    { id: 23666, parentId: null, name: 'Test9', type: 'xlsx', size: 2048, date: '2020-11-01' },
    { id: 23677, parentId: 23666, name: 'Test10', type: 'js', size: 1024, date: '2021-06-01' },
    { id: 23671, parentId: 23677, name: 'Test11', type: 'js', size: 1024, date: '2021-06-01' },
    { id: 23672, parentId: 23677, name: 'Test12', type: 'js', size: 1024, date: '2021-06-01' },
    { id: 23688, parentId: 23666, name: 'Test13', type: 'js', size: 1024, date: '2021-06-01' },
    { id: 23681, parentId: 23688, name: 'Test14', type: 'js', size: 1024, date: '2021-06-01' },
    { id: 23682, parentId: 23688, name: 'Test15', type: 'js', size: 1024, date: '2021-06-01' },
    { id: 24555, parentId: null, name: 'Test16', type: 'avi', size: 224, date: '2020-10-01' },
    { id: 24566, parentId: 24555, name: 'Test17', type: 'js', size: 1024, date: '2021-06-01' },
    { id: 24577, parentId: 24555, name: 'Test18', type: 'js', size: 1024, date: '2021-06-01' }
  ]
})
</script>

可编辑表格

在这里插入图片描述

<template>
  <div>
    <vxe-toolbar>
      <template #buttons>
        <vxe-button @click="insertEvent">新增</vxe-button>
        <vxe-button @click="removeSelectEvent()">删除选中</vxe-button>
        <vxe-button @click="validAllEvent">校验全表单元格</vxe-button>
        <vxe-button @click="getSelectEvent">获取选中</vxe-button>
        <vxe-button @click="getInsertEvent">获取新增</vxe-button>
        <vxe-button @click="getRemoveEvent">获取删除</vxe-button>
        <vxe-button @click="getUpdateEvent">获取修改</vxe-button>
      </template>
    </vxe-toolbar>

    <vxe-table
      border
      show-overflow
      keep-source
      ref="tableRef"
      :data="tableData"
      :edit-rules="validRules"
      :edit-config="{trigger: 'click', mode: 'row', showStatus: true}"
      :valid-config="{msgMode: 'full'}">
      <vxe-column type="checkbox" width="80"></vxe-column>
      <vxe-column type="seq" width="80"></vxe-column>
      <vxe-column field="name" title="Name" width="400" :edit-render="{}">
        <template #edit="slotParams">
          <vxe-input v-model="slotParams.row.name" type="text" @change="changeCellEvent(slotParams)"></vxe-input>
        </template>
      </vxe-column>
      <vxe-column field="age" title="Age" width="200" :edit-render="{}">
        <template #edit="slotParams">
          <vxe-input v-model="slotParams.row.age" type="text" @change="changeCellEvent(slotParams)"></vxe-input>
        </template>
      </vxe-column>
      <vxe-column field="sex" title="Sex" width="200" :edit-render="{}">
        <template #edit="slotParams">
          <vxe-input v-model="slotParams.row.sex" type="text" @change="changeCellEvent(slotParams)"></vxe-input>
        </template>
      </vxe-column>
      <vxe-column field="date" title="Date" width="300" fixed="right" :edit-render="{}">
        <template #edit="slotParams">
          <vxe-input v-model="slotParams.row.date" type="date" @change="changeCellEvent(slotParams)"></vxe-input>
        </template>
      </vxe-column>
    </vxe-table>
  </div>
</template>

<script lang="jsx" setup>
import { ref } from 'vue'
import { VxeUI } from 'vxe-table'
const tableRef = ref()
const tableData = ref([
  { id: 10001, name: 'Test1', role: 'Develop', sex: '0', age: 28, address: 'test abc' },
  { id: 10002, name: '', role: 'Test', sex: '1', age: 22, address: 'Guangzhou' },
  { id: 10003, name: 'Test3', role: 'PM', sex: '', age: 32, address: 'Shanghai' },
  { id: 10004, name: '', role: '', sex: '1', age: 23, address: 'test abc' },
  { id: 10005, name: 'Test5', role: '', sex: '', age: 30, address: 'Shanghai' },
  { id: 10006, name: 'Test6', role: 'Designer', sex: '1', age: 21, address: 'test abc' }
])
const validRules = ref({
  name: [
    {
      validator ({ cellValue }) {
        if (cellValue && !/^\w+$/.test(cellValue)) {
          return new Error('名称格式不正确,必须字母或数字')
        }
      }
    }
  ],
  sex: [
    { required: true, message: '性别必须填写' }
  ],
  age: [
    { type: 'number', min: 10, max: 100000, message: '输入 10 ~ 100000 范围' }
  ],
  date: [
    { required: true, message: '日期必须填写' }
  ]
})
const validAllEvent = async () => {
  const $table = tableRef.value
  if ($table) {
    const errMap = await $table.fullValidate(true)
    if (errMap) {
      const msgList = []
      Object.values(errMap).forEach((errList) => {
        errList.forEach((params) => {
          const { rowIndex, column, rules } = params
          rules.forEach((rule) => {
            msgList.push(`${rowIndex + 1}${column.title} 校验错误:${rule.message}`)
          })
        })
      })
      VxeUI.modal.message({
        status: 'error',
        slots: {
          default () {
            return (<div class="red" style="max-height: 400px;overflow: auto;">
                  {msgList.map(msg => <div>{msg}</div>)}
                </div>)
          }
        }
      })
    } else {
      VxeUI.modal.message({ status: 'success', message: '校验成功!' })
    }
  }
}
const changeCellEvent = (params) => {
  const $table = tableRef.value
  if ($table) {
    $table.updateStatus(params)
  }
}
const removeSelectEvent = () => {
  const $table = tableRef.value
  if ($table) {
    $table.removeCheckboxRow()
  }
}
const insertEvent = async () => {
  const $table = tableRef.value
  if ($table) {
    const { row: newRow } = await $table.insert({})
    // 插入一条数据并触发校验
    const errMap = await $table.validate(newRow)
    if (errMap) {
      // 校验失败
    }
  }
}
const getSelectEvent = () => {
  const $table = tableRef.value
  if ($table) {
    const selectRecords = $table.getCheckboxRecords()
    VxeUI.modal.alert(selectRecords.length)
  }
}
const getInsertEvent = () => {
  const $table = tableRef.value
  if ($table) {
    const insertRecords = $table.getInsertRecords()
    VxeUI.modal.alert(insertRecords.length)
  }
}
const getRemoveEvent = () => {
  const $table = tableRef.value
  if ($table) {
    const removeRecords = $table.getRemoveRecords()
    VxeUI.modal.alert(removeRecords.length)
  }
}
const getUpdateEvent = () => {
  const $table = tableRef.value
  if ($table) {
    const updateRecords = $table.getUpdateRecords()
    VxeUI.modal.alert(updateRecords.length)
  }
}
</script>

内置分页查询

可以自己调用接口,也可以使用数据代理方式,配置一个查询方法就可以自动加载
在这里插入图片描述

<template>
  <div>
    <vxe-grid v-bind="gridOptions"></vxe-grid>
  </div>
</template>

<script setup>
import { reactive } from 'vue'
const list = [
  { id: 10001, name: 'Test1', nickname: 'T1', role: 'Develop', sex: 'Man', age: 28, address: 'Shenzhen' },
  { id: 10002, name: 'Test2', nickname: 'T2', role: 'Test', sex: 'Women', age: 22, address: 'Guangzhou' },
  { id: 10003, name: 'Test3', nickname: 'T3', role: 'PM', sex: 'Man', age: 32, address: 'Shanghai' },
  { id: 10004, name: 'Test4', nickname: 'T4', role: 'Designer', sex: 'Women', age: 23, address: 'test abc' },
  { id: 10005, name: 'Test5', nickname: 'T5', role: 'Develop', sex: 'Women', age: 30, address: 'Shanghai' },
  { id: 10006, name: 'Test6', nickname: 'T6', role: 'Designer', sex: 'Women', age: 21, address: 'Shenzhen' },
  { id: 10007, name: 'Test7', nickname: 'T7', role: 'Test', sex: 'Man', age: 29, address: 'Shenzhen' },
  { id: 10008, name: 'Test8', nickname: 'T8', role: 'Develop', sex: 'Man', age: 35, address: 'test abc' },
  { id: 10009, name: 'Test9', nickname: 'T9', role: 'Develop', sex: 'Man', age: 35, address: 'Shenzhen' },
  { id: 100010, name: 'Test10', nickname: 'T10', role: 'Develop', sex: 'Man', age: 35, address: 'Guangzhou' },
  { id: 100011, name: 'Test11', nickname: 'T11', role: 'Develop', sex: 'Man', age: 49, address: 'Guangzhou' },
  { id: 100012, name: 'Test12', nickname: 'T12', role: 'Develop', sex: 'Women', age: 45, address: 'Shanghai' },
  { id: 100013, name: 'Test13', nickname: 'T13', role: 'Test', sex: 'Women', age: 35, address: 'Guangzhou' },
  { id: 100014, name: 'Test14', nickname: 'T14', role: 'Test', sex: 'Man', age: 29, address: 'Shanghai' },
  { id: 100015, name: 'Test15', nickname: 'T15', role: 'Develop', sex: 'Man', age: 39, address: 'Guangzhou' },
  { id: 100016, name: 'Test16', nickname: 'T16', role: 'Test', sex: 'Women', age: 35, address: 'Guangzhou' },
  { id: 100017, name: 'Test17', nickname: 'T17', role: 'Test', sex: 'Man', age: 39, address: 'Shanghai' },
  { id: 100018, name: 'Test18', nickname: 'T18', role: 'Develop', sex: 'Man', age: 44, address: 'Guangzhou' },
  { id: 100019, name: 'Test19', nickname: 'T19', role: 'Develop', sex: 'Man', age: 39, address: 'Guangzhou' },
  { id: 100020, name: 'Test20', nickname: 'T20', role: 'Test', sex: 'Women', age: 35, address: 'Guangzhou' },
  { id: 100021, name: 'Test21', nickname: 'T21', role: 'Test', sex: 'Man', age: 39, address: 'Shanghai' },
  { id: 100022, name: 'Test22', nickname: 'T22', role: 'Develop', sex: 'Man', age: 44, address: 'Guangzhou' }
]
// 模拟接口
const findPageList = (pageSize, currentPage) => {
  console.log(`调用查询接口 pageSize=${pageSize} currentPage=${currentPage}`)
  return new Promise(resolve => {
    setTimeout(() => {
      resolve({
        result: list.slice((currentPage - 1) * pageSize, currentPage * pageSize),
        page: {
          total: list.length
        }
      })
    }, 100)
  })
}
const gridOptions = reactive({
  border: true,
  height: 500,
  pagerConfig: {},
  proxyConfig: {
    // props: {
    //   result: 'result', // 配置响应结果列表字段
    //   total: 'page.total' // 配置响应结果总页数字段
    // },
    ajax: {
      query: ({ page }) => {
        // 默认接收 Promise<{ result: [], page: { total: 100 } }>
        return findPageList(page.pageSize, page.currentPage)
      }
    }
  },
  columns: [
    { type: 'seq', width: 70 },
    { field: 'name', title: 'Name' },
    { field: 'nickname', title: 'Nickname' },
    { field: 'role', title: 'Role' },
    { field: 'address', title: 'Address', showOverflow: true }
  ]
})
</script>

实现表格搜索

在这里插入图片描述

<template>
  <div>
    <p>
      <vxe-input v-model="filterName" type="search" placeholder="试试全表搜索" @keyup="searchEvent"></vxe-input>
    </p>

    <vxe-table
      border
      class="mylist-table"
      height="400"
      :column-config="{useKey: true}"
      :row-config="{useKey: true}"
      :data="list">
      <vxe-column type="seq" width="80"></vxe-column>
      <vxe-column field="name" title="Name" type="html"></vxe-column>
      <vxe-column field="role" title="Role" type="html"></vxe-column>
      <vxe-column field="age" title="Age" type="html"></vxe-column>
      <vxe-column field="address" title="Address" type="html"></vxe-column>
    </vxe-table>
  </div>
</template>

<script setup>
import { ref } from 'vue'
const filterName = ref('')
const list = ref([])
const tableData = ref([
  { id: 10001, name: 'Test1', role: 'Develop', sex: '0', age: 28, amount: 888, address: 'test abc' },
  { id: 10002, name: 'Test2', role: 'Test', sex: '1', age: 22, amount: 666, address: 'Guangzhou' },
  { id: 10003, name: 'Test3', role: 'PM', sex: '1', age: 32, amount: 89, address: 'Shanghai' },
  { id: 10004, name: 'Test4', role: 'Designer', sex: '0', age: 23, amount: 1000, address: 'test abc' },
  { id: 10005, name: 'Test5', role: 'Develop', sex: '0', age: 30, amount: 999, address: 'Shanghai' },
  { id: 10006, name: 'Test6', role: 'Designer', sex: '0', age: 21, amount: 998, address: 'test abc' },
  { id: 10007, name: 'Test7', role: 'Test', sex: '1', age: 29, amount: 2000, address: 'test abc' },
  { id: 10008, name: 'Test8', role: 'Develop', sex: '1', age: 35, amount: 999, address: 'test abc' },
  { id: 10009, name: 'Test9', role: 'Test', sex: '1', age: 26, amount: 2000, address: 'test abc' },
  { id: 100010, name: 'Test10', role: 'Develop', sex: '1', age: 21, amount: 666, address: 'test abc' }
])
const searchEvent = () => {
  const filterVal = String(filterName.value).trim().toLowerCase()
  if (filterVal) {
    const filterRE = new RegExp(filterVal, 'gi')
    const searchProps = ['name', 'role', 'age', 'address']
    const rest = tableData.value.filter(item => searchProps.some(key => String(item[key]).toLowerCase().indexOf(filterVal) > -1))
    list.value = rest.map(row => {
      const item = Object.assign({}, row)
      searchProps.forEach(key => {
        item[key] = String(item[key]).replace(filterRE, match => `<span class="keyword-highlight">${match}</span>`)
      })
      return item
    })
  } else {
    list.value = tableData.value
  }
}
searchEvent()
</script>

<style lang="scss" scoped>
.mylist-table {
  ::v-deep(.keyword-highlight)  {
    background-color: #FFFF00;
  }
}
</style>

虚拟滚动,加载大量数据

在这里插入图片描述

<template>
  <div>
    <vxe-table
      border
      show-overflow
      height="600"
      :scroll-y="{enabled: true, gt: 0}"
      :data="tableData">
      <vxe-column type="seq" width="70"></vxe-column>
      <vxe-column field="name" title="Name"></vxe-column>
      <vxe-column field="role" title="Role"></vxe-column>
      <vxe-column field="sex" title="Sex"></vxe-column>
    </vxe-table>
  </div>
</template>

<script setup>
import { ref } from 'vue'
const tableData = ref([])
// 模拟行数据
const loadList = (size = 200) => {
  const dataList = []
  for (let i = 0; i < size; i++) {
    dataList.push({
      id: 10000 + i,
      name: 'Test' + i,
      role: 'Developer',
      sex: '男'
    })
  }
  tableData.value = dataList
}
loadList(500)
</script>

分页打印功能

支持各种打印,如果数据导出 csv.、xlsx 等,则需要 安装扩展插件在这里插入图片描述

<template>
  <div>
    <vxe-button @click="printEvent">分页打印表格</vxe-button>

    <vxe-table
      border
      height="500"
      ref="tableRef"
      :data="tableData">
      <vxe-column field="id" title="ID" width="60"></vxe-column>
      <vxe-column field="name" title="Name"></vxe-column>
      <vxe-column field="sex" title="Sex"></vxe-column>
      <vxe-column field="address" title="Address"></vxe-column>
    </vxe-table>
  </div>
</template>

<script setup>
import { ref } from 'vue'
import { VxeUI } from 'vxe-table'
import XEUtils from 'xe-utils'
const tableRef = ref()
const list = []
for (let i = 0; i < 100; i++) {
  list.push({
    id: 10001 + i,
    name: 'Test1',
    role: 'Develop',
    sex: 'Man',
    address: 'test abc'
  })
}
const tableData = ref(list)
const printEvent = () => {
  const $table = tableRef.value
  if ($table) {
    // 分割每页26条
    Promise.all(XEUtils.chunk(tableData.value, 26).map(pageData => {
      return $table.getPrintHtml({
        data: pageData
      }).then(({ html }) => {
        return {
          bodyHtml: html
        }
      })
    })).then(pageBreaks => {
      VxeUI.print({
        title: '分页打印表格',
        showPageNumber: true,
        pageBreaks
      })
    })
  }
}
</script>

单元格选取

在这里插入图片描述

单元格复制粘贴 Excel

支持从表格、WPC、Excel等互相复制粘贴、等
在这里插入图片描述

以下为 UI 部分

折叠表单

在这里插入图片描述
在这里插入图片描述

<template>
  <div>
    <vxe-form v-bind="formOptions" v-on="formEvents" ></vxe-form>
  </div>
</template>

<script setup>
import { reactive } from 'vue'
import { VxeUI } from 'vxe-pc-ui'
const formOptions = reactive({
  titleWidth: 100,
  titleColon: true,
  titleAlign: 'right',
  data: {
    name: 'test1',
    role: '',
    nickname: 'Testing',
    sex: '',
    age: '',
    num: '',
    createDate: '',
    updateDate: ''
  },
  items: [
    { field: 'name', title: '名称', span: 12, itemRender: { name: 'VxeInput' } },
    { field: 'nickname', title: '昵称', span: 12, itemRender: { name: 'VxeInput' } },
    { field: 'role', title: '角色', span: 12, folding: true, itemRender: { name: 'VxeInput' } },
    { field: 'sex', title: '性别', span: 12, folding: true, itemRender: { name: 'VxeInput' } },
    { field: 'age', title: '年龄', span: 12, folding: true, itemRender: { name: 'VxeInput' } },
    { field: 'num', title: '大小', span: 12, folding: true, itemRender: { name: 'VxeInput' } },
    { field: 'createDate', title: '创建时间', span: 12, folding: true, itemRender: { name: 'VxeInput' } },
    { field: 'updateDate', title: '更新时间', span: 12, folding: true, itemRender: { name: 'VxeInput' } },
    {
      align: 'center',
      span: 24,
      collapseNode: true,
      itemRender: {
        name: 'VxeButtonGroup',
        options: [
          { type: 'submit', content: '搜索', status: 'primary' },
          { type: 'reset', content: '重置' }
        ]
      }
    }
  ]
})
const formEvents = {
  submit () {
    VxeUI.modal.message({ content: '搜索', status: 'success' })
  }
}
</script>

窗口最大化与最小化

在这里插入图片描述

<template>
  <div>
    <vxe-button @click="openVerticalEvent">点击弹出</vxe-button>
  </div>
</template>

<script setup>
import { VxeUI } from 'vxe-pc-ui'
let num = 1
const openVerticalEvent = () => {
  VxeUI.modal.open({
    title: `标题 ${num}`,
    content: `我是第 ${num} 个,点击最小化纵向排列`,
    mask: false,
    lockView: false,
    escClosable: true,
    width: 600,
    height: 400,
    showZoom: true,
    zoomConfig: {
      minimizeLayout: 'vertical'
    }
  })
  num++
}
</script>

树组件

在这里插入图片描述

<template>
  <div>
    <vxe-tree
      show-radio
      :data="treeList"
      v-model:check-node-key="checkNodeKey"
      :node-config="nodeConfig"
      :radio-config="radioConfig">
    </vxe-tree>
  </div>
</template>

<script setup>
import { ref, reactive } from 'vue'
const checkNodeKey = ref(3)
const radioConfig = reactive({
  highlight: true
})
const nodeConfig = reactive({
  isHover: true
})
const treeList = ref([
  { title: '节点2', id: '2' },
  {
    title: '节点3',
    id: '3',
    children: [
      { title: '节点3-1', id: '31' },
      {
        title: '节点3-2',
        id: '32',
        children: [
          { title: '节点3-2-1', id: '321' },
          { title: '节点3-2-2', id: '322' }
        ]
      },
      {
        title: '节点3-3',
        id: '33',
        children: [
          { title: '节点3-3-1', id: '331' },
          { title: '节点3-3-2', id: '332' },
          { title: '节点3-3-3', id: '333' }
        ]
      },
      { title: '节点3-4', id: '34' }
    ]
  },
  {
    title: '节点4',
    id: '4',
    children: [
      {
        title: '节点4-1',
        id: '41',
        children: [
          { title: '节点4-1-1', id: '411' },
          { title: '节点4-1-2', id: '412' }
        ]
      },
      { title: '节点4-2', id: '42' },
      {
        title: '节点4-3',
        id: '43',
        children: [
          { title: '节点4-3-1', id: '431' },
          { title: '节点4-3-2', id: '432' }
        ]
      }
    ]
  },
  { title: '节点5', id: '5' }
])
</script>

可视化设计器

支持自定义添加控件。自定义渲染等,功能太多,去看官网。。
在这里插入图片描述
列表设计器
在这里插入图片描述
首页设计器
在这里插入图片描述

功能实现是太多了,具体细节只能去看官网文档:

Vxe 表格库Vxe UI库、以及通用的 函数库

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值