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

news2024/11/27 22:45:00

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>

窗口最大化与最小化

在这里插入图片描述

<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>

分页打印功能

支持各种打印,如果数据导出 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等互相复制粘贴、等
在这里插入图片描述

可视化设计器

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2062712.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

YOLOv5改进 | 融合改进 | C3 融合Dilated Reparam Block提升检测效果【附代码+小白可上手】

秋招面试专栏推荐 &#xff1a;深度学习算法工程师面试问题总结【百面算法工程师】——点击即可跳转 &#x1f4a1;&#x1f4a1;&#x1f4a1;本专栏所有程序均经过测试&#xff0c;可成功执行&#x1f4a1;&#x1f4a1;&#x1f4a1; 专栏目录&#xff1a; 《YOLOv5入门 改…

电脑照片删除了怎么恢复回来?轻松三步,找回珍贵记忆

在数字时代&#xff0c;我们的电脑里储存了无数珍贵的照片&#xff0c;它们记录着生活的点滴&#xff0c;承载着美好的回忆。然而&#xff0c;一不小心将照片删除&#xff0c;往往会让人心急如焚。别担心&#xff0c;本文将为你详细介绍如何恢复电脑中被删除的照片&#xff0c;…

制造企业WMS库存盘点的应用

1.库存盘点的重要性与挑战 1.1 盘点目的与意义 库存盘点是制造工厂WMS系统中的一项基础性工作&#xff0c;其目的在于确保库存数据的准确性&#xff0c;从而为生产计划、物料需求计划、成本核算等提供可靠的数据支持。盘点的意义主要体现在以下几个方面&#xff1a; - 确保数…

PYUSD跃升为第六大稳定币:借势Solana和高APY的成功之道

随着加密市场的不断发展&#xff0c;稳定币在数字资产生态系统中的重要性日益凸显。PayPal旗下的美元稳定币PYUSD凭借强大的市场背景和策略性扩展&#xff0c;已经迅速成长为第六大稳定币。特别是在与Solana区块链的深度合作&#xff0c;以及高APY&#xff08;年化收益率&#…

数据可视化~~看板的切换设置+光滑折线图

目录 1.问题背景 2.安装模块 3.绘制柱状图的实现 4.对于图表的完善 5.重新思索 1.问题背景 我们想要通过这个用户的获得点赞的数量和她的粉丝数量的比值作为一个指标&#xff0c;我们想要绘制一个柱状图取值管的进行这个排名&#xff1b; 下面的这个是今天最后我们实现的…

飞睿智能10km无人机WiFi中继图传模块,视界无界,高速传输画质高清不卡顿、抗干扰

在无人机技术日新月异的今天&#xff0c;我们时常被那些高空翱翔的“小眼睛”所震撼。它们不仅为我们带来了未有的视觉体验&#xff0c;更在诸多领域发挥着举足轻重的作用。然而&#xff0c;要让无人机真正发挥其潜力&#xff0c;一个稳定、高效的图传系统至关重要。今天&#…

vue2 动态组件

文章目录 实现思路&#xff1a;组件注册动态组件嵌入的位置动态的tabPanes动态组件 - listComponent实际嵌入的组件 - invoiceListComponent 实现思路&#xff1a; 组件注册 组件的地址存储在表中&#xff0c;在xxx_components表中配置组件url components_key&#xff1a;组…

2024年最新股指期货交易手续费标准是多少?

股指期货交易手续费是指投资者在进行股指期货买卖时需要支付的费用&#xff0c;主要包括开仓手续费和平仓手续费。这些费用是交易所和期货公司为了维持市场运行和提供服务而收取的。 一、沪深300、上证50、中证500、中证1000股指期货手续费 日内交易&#xff1a;只要你在交易…

计算机中的「null」怎么读?

今天咱们来聊一个让无数程序员纠结的问题&#xff1a;“null”这个词到底该怎么读&#xff1f; 在开始讨论这个问题之前&#xff0c;我觉得有必要先带大家回忆一下我们曾经踩过的那些发音雷区。 尤其是那些英文术语&#xff0c;真的是一个坑接一个。比如这些常见的发音错误&am…

常见DDoS攻击之零日漏洞Zero-day Attacks

目录 一、什么是零日漏洞Zero-day Attacks 二、零日漏洞是如何转化为零日攻击的 三、常见的零日攻击类型 四、为什么零日攻击很危险 五、著名的零日攻击事件 六、如何降低零日攻击的风险 七、DDoS攻击防御解决方案&#xff08;定制化&#xff09; 7.1 产品优势 7.2 产品…

Vue - 详细介绍wow.js滚动触发动画组件(Vue2 Vue3)

Vue - 详细介绍wow.js滚动触发动画组件&#xff08;Vue2 & Vue3&#xff09; 在日常网页中&#xff0c;我们难免会用到CSS动画来对某些元素进行显示隐藏&#xff0c;在wowjs中可根据浏览器滚动来触发对应的CSS动画&#xff0c;并且可设置多种animate动画类型、动画持续时间…

速卖通自养号测评:安全高效提升产品销量的秘诀

速卖通自养号测评是跨境电商卖家为了提升产品销量、评价数量及排名而采取的一种策略。以下是对速卖通自养号测评的详细解析&#xff1a; 一、自养号测评的定义 自养号测评&#xff0c;顾名思义&#xff0c;是指卖家自行培养并管理买家账号&#xff0c;通过模拟真实买家的购物…

重新认识一下,从BIO到NIO,再到AIO,响应式编程

Netty 的高性能架构&#xff0c;是基于一个网络编程设计模式 Reactor 进行设计的。现在&#xff0c;大多数与 I/O 相关的组件&#xff0c;都会使用 Reactor 模型&#xff0c;比如 Tomcat、Redis、Nginx 等&#xff0c;可见 Reactor 应用的广泛性。 Reactor 是 NIO 的基础。为什…

WordPress中最佳免费WooCommerce主题推荐:专家级指南

在电商领域&#xff0c;每个创业者的梦想是拥有一个既功能强大又美观的在线商店。对于已经具备一定建站经验的专家级用户来说&#xff0c;重点是选择一款功能强大且灵活性高的WooCommerce主题。在这篇文章中&#xff0c;我将为大家推荐几款适合专家级用户的免费WooCommerce主题…

javaer选手快速入门grpc

本文前置内容 需要学过java微服务开发,至少知道使用过openfeign和dubbo等rpc微服务组件的相关内容 相信已经学习到微服务开发的对grpc或多或少都有了解,高效的性能和protobuf这样轻量序列化的方式 无论是go开发必学还是java 使用dubbo或者其他深入也是需要了解的 相关概念 Pro…

使用js代码模拟React页面中input文本框输入

遇到的问题&#xff1a; 使用js代码模拟input框中输入指定的字符串&#xff0c;在浏览器调试页面能看到输入框的文字已经变成我需要的文字&#xff0c;但是只要我点击输入框&#xff0c;或者页面上的其他输入框&#xff0c;输入框的文字就清空了。 解决过程和方法&#xff1a; …

火语言RPA流程组件介绍--睡眠等待

&#x1f6a9;【组件功能】&#xff1a;休眠等待指定时间后再恢复执行 阻塞当前流程继续向下运行&#xff0c;暂停等待指定时间&#xff0c;一般当上一组件操作需要缓冲时间或完成太快需要休眠观测时使用此组件。 配置预览 配置说明 延迟时间 支持T或# 输入仅支持整型 阻塞…

[Linux#44][线程] CP模型2.0 | 信号量接口 | 基于环形队列

目录 1.回忆 Task.hpp 1. #pragma once 2. 头文件和命名空间 3. 类 CallTask 4. 操作符字符串 5. 回调函数 mymath 阻塞队列 BlockQueue 的实现 BlockQueue 生产者和消费者线程 生产者productor 消费者 consumer 主函数 main 代码整体说明 2. 信号量 2.1 回忆&…

简化登录流程,助力应用建立用户体系

随着智能手机和移动应用的普及&#xff0c;用户需要在不同的应用中注册和登录账号&#xff0c;传统的账号注册和登录流程需要用户输入用户名和密码&#xff0c;这不仅繁琐而且容易造成用户流失。 华为账号服务&#xff08;Account Kit&#xff09;提供简单、快速、安全的登录功…

Raft分区产生的脏读问题

Raft分区产生的脏读问题 前言网络分区情况1 4和5分到一个分区&#xff0c;即当前leader依然在多数分区情况2 1和2分到一个分区&#xff0c;即当前leader在少数分区 脏读问题的解决官方解答其他论文 参考链接 前言 昨天面试阿里云被问到了这个问题&#xff0c;在此记录一下。 …