前言
hello world欢迎来到前端的新世界
😜当前文章系列专栏:前端系列文章
🐱👓博主在前端领域还有很多知识和技术需要掌握,正在不断努力填补技术短板。(如果出现错误,感谢大家指出)🌹
💖感谢大家支持!您的观看就是作者创作的动力
vxe-table
一款专门用来对Vue3表格进行复杂操作的ui组件库,虚拟滚动,普通表格的行拖拽,表格的全屏展示,表格的全键盘操作,禁用编辑等。
官网
下载
npm install xe-utils vxe-table
配置在main.js或者main.ts里面
import { App, createApp } from 'vue' import VXETable from 'vxe-table' import 'vxe-table/lib/style.css' function useTable (app: App) { app.use(VXETable) } createApp(App).use(useTable).mount('#app')
实现表头拖拽
直接复制
<template> <div> <vxe-grid v-bind="gridOptions"> <template #toolbar_buttons> <vxe-button @click="gridOptions.align = 'left'">居左</vxe-button> <vxe-button @click="gridOptions.align = 'center'">居中</vxe-button> <vxe-button @click="gridOptions.align = 'right'">居右</vxe-button> </template> </vxe-grid> </div> </template> <script lang="ts" setup> import { reactive } from 'vue' import { VxeGridProps } from 'vxe-table' interface RowVO { id: number name: string nickname: string role: string sex: string age: number address: string } const gridOptions = reactive<VxeGridProps<RowVO>>({ border: true, height: 300, align: null, columnConfig: { resizable: true }, columns: [ { type: 'seq', width: 50 }, { field: 'name', title: 'name' }, { field: 'sex', title: 'sex' }, { field: 'address', title: 'Address' } ], toolbarConfig: { slots: { buttons: 'toolbar_buttons' } }, 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' }, { 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: 'Shenzhen' } ] }) </script>
树形表格
<template> <div> <vxe-toolbar> <template #buttons> <vxe-button @click="expandAllEvent">展开所有</vxe-button> <vxe-button @click="claseExpandEvent">收起所有</vxe-button> </template> </vxe-toolbar> <vxe-table show-overflow height="400" ref="tableRef" :loading="loading" :tree-config="{transform: true}" :scroll-y="{enabled: true, gt: 20}" :data="tableData"> <vxe-column type="seq" width="200" tree-node></vxe-column> <vxe-column field="id" title="Id"></vxe-column> <vxe-column field="name" title="Name"></vxe-column> </vxe-table> </div> </template> <script lang="ts" setup> import { ref } from 'vue' import { VxeTableInstance } from 'vxe-table' interface RowVO { id: number parentId: number | null name: string } const tableRef = ref<VxeTableInstance<RowVO>>() const loading = ref(false) const tableData = ref<RowVO[]>([]) const loadList = () => { loading.value = true fetch('/resource/json/provinces_list.json').then(res => res.json()).then((data: RowVO[]) => { tableData.value = data loading.value = false }) } const expandAllEvent = () => { const $table = tableRef.value if ($table) { $table.setAllTreeExpand(true) } } const claseExpandEvent = () => { const $table = tableRef.value if ($table) { $table.clearTreeExpand() } } loadList() </script>
全键盘操作
template
<vxe-toolbar :refresh="{query: findList}"> <template #buttons> <vxe-button> <template #default>新增操作</template> <template #dropdowns> <vxe-button type="text" @click="insertEvent(null)">从第一行插入</vxe-button> <vxe-button type="text" @click="insertEvent(-1)">从最后插入</vxe-button> <vxe-button type="text" @click="insertEvent($refs.xTable.getData(100))">插入到 100 行</vxe-button> <vxe-button type="text" @click="insertEvent($refs.xTable.getData(400))">插入到 400 行</vxe-button> </template> </vxe-button> <vxe-button> <template #default>删除操作</template> <template #dropdowns> <vxe-button type="text" @click="$refs.xTable.removeCheckboxRow()">删除选中</vxe-button> <vxe-button type="text" @click="$refs.xTable.remove($refs.xTable.getData(0))">删除第一行</vxe-button> <vxe-button type="text" @click="$refs.xTable.remove($refs.xTable.getData($refs.xTable.getData().length - 1))">删除最后一行</vxe-button> <vxe-button type="text" @click="$refs.xTable.remove($refs.xTable.getData(100))">删除第 100 行</vxe-button> </template> </vxe-button> <vxe-button> <template #default>校验操作</template> <template #dropdowns> <vxe-button type="text" @click="validEvent">快速校验</vxe-button> <vxe-button type="text" @click="fullValidEvent">完整快速校验</vxe-button> <vxe-button type="text" @click="selectValidEvent">选中行校验</vxe-button> </template> </vxe-button> <vxe-button @click="getInsertEvent">获取新增</vxe-button> <vxe-button @click="getRemoveEvent">获取删除</vxe-button> <vxe-button @click="getUpdateEvent">获取修改</vxe-button> <vxe-button> <template #default>滚动操作</template> <template #dropdowns> <vxe-button type="text" @click="$refs.xTable.scrollToRow($refs.xTable.getData(10))">滚动到第 10 行</vxe-button> <vxe-button type="text" @click="$refs.xTable.scrollToRow($refs.xTable.getData(400))">滚动第 400 行</vxe-button> <vxe-button type="text" @click="$refs.xTable.scrollToColumn($refs.xTable.getColumns(1))">滚动第 1 列</vxe-button> <vxe-button type="text" @click="$refs.xTable.scrollToColumn($refs.xTable.getColumns(10))">滚动第 10 列</vxe-button> </template> </vxe-button> </template> </vxe-toolbar> <vxe-table border show-overflow keep-source ref="xTable" height="300" :column-config="{resizable: true}" :loading="demo1.loading" :edit-rules="demo1.validRules" :mouse-config="{selected: true}" :edit-config="{trigger: 'dblclick', mode: 'cell', showStatus: true}" :keyboard-config="{isArrow: true, isDel: true, isEnter: true, isTab: true, isEdit: true}"> <vxe-column type="checkbox" width="60"></vxe-column> <vxe-column type="seq" width="100"></vxe-column> <vxe-column field="name" title="Name" sortable width="200" :edit-render="{autofocus: '.vxe-input--inner'}"> <template #edit="scope"> <vxe-input v-model="scope.row.name" type="text" @change="$refs.xTable.updateStatus(scope)"></vxe-input> </template> </vxe-column> <vxe-column field="age" title="Age" width="200" :edit-render="{autofocus: '.vxe-input--inner'}"> <template #edit="scope"> <vxe-input v-model="scope.row.age" type="text" @change="$refs.xTable.updateStatus(scope)"></vxe-input> </template> </vxe-column> <vxe-column field="sex" title="Sex" width="200" :edit-render="{autofocus: '.vxe-input--inner'}"> <template #edit="scope"> <vxe-input v-model="scope.row.sex" type="text" @change="$refs.xTable.updateStatus(scope)"></vxe-input> </template> </vxe-column> <vxe-column field="rate" title="Rate" width="200"></vxe-column> <vxe-column field="region" title="Region" width="200"></vxe-column> <vxe-column field="time" title="Time" width="200"></vxe-column> <vxe-column field="address" title="Address" width="300" show-overflow></vxe-column> <vxe-column field="updateTime" title="UpdateTime" width="200"></vxe-column> <vxe-column field="createTime" title="CreateTime" width="200"></vxe-column> </vxe-table>
script
import { defineComponent, reactive, ref } from 'vue' import { VXETable, VxeTableInstance, VxeTablePropTypes } from 'vxe-table' export default defineComponent({ setup () { const xTable = ref<VxeTableInstance>() const demo1 = reactive({ loading: false, validRules: { name: [ { required: true, message: 'app.body.valid.rName' }, { min: 3, max: 50, message: '名称长度在 3 到 50 个字符' } ], sex: [ { required: true, message: '性别必须填写' } ] } as VxeTablePropTypes.ValidConfig }) const mockList = (size: number) => { const list: any[] = [] for (let index = 0; index < size; index++) { list.push({ checked: false, name: `名称${index}`, sex: '0', num: 123, age: 18, num2: 234, rate: 3, address: 'shenzhen' }) } return list } const findList = () => { demo1.loading = true return new Promise(resolve => { setTimeout(() => { const tableData = mockList(600) // 阻断 vue 对大数组的监听,避免 vue 绑定大数据造成短暂的卡顿 const $table = xTable.value if ($table) { $table.loadData(tableData) } resolve(null) demo1.loading = false }, 300) }) } const validEvent = async () => { const $table = xTable.value const errMap = await $table.validate() if (errMap) { VXETable.modal.message({ status: 'error', content: '校验不通过!' }) } else { VXETable.modal.message({ status: 'success', content: '校验成功!' }) } } const fullValidEvent = async () => { const $table = xTable.value const errMap = await $table.fullValidate() if (errMap) { const msgList: string[] = [] Object.values(errMap).forEach((errList) => { errList.forEach(params => { const { rowIndex, column, rules } = params rules.forEach(rule => { msgList.push(`第 ${rowIndex + 1} 行 ${column.title} 校验错误:${rule.message}`) }) }) }) VXETable.modal.message({ status: 'error', slots: { default () { return [ <div class="red" style="max-height: 400px;overflow: auto;"> { msgList.map(msg => { return <div>{ msg }</div> }) } </div> ] } } }) } else { VXETable.modal.message({ status: 'success', content: '校验成功!' }) } } const selectValidEvent = async () => { const $table = xTable.value const selectRecords = $table.getCheckboxRecords() if (selectRecords.length > 0) { const errMap = await $table.validate(selectRecords).catch(errMap => errMap) if (errMap) { VXETable.modal.message({ status: 'error', content: '校验不通过!' }) } else { VXETable.modal.message({ status: 'success', content: '校验成功!' }) } } else { VXETable.modal.message({ status: 'warning', content: '未选中数据!' }) } } const insertEvent = (row: any) => { const $table = xTable.value const record = { checked: false } $table.insertAt(record, row).then(({ row }) => { $table.setEditRow(row) }) } const getInsertEvent = () => { const $table = xTable.value const insertRecords = $table.getInsertRecords() VXETable.modal.alert(insertRecords.length) } const getRemoveEvent = () => { const $table = xTable.value const removeRecords = $table.getRemoveRecords() VXETable.modal.alert(removeRecords.length) } const getUpdateEvent = () => { const $table = xTable.value const updateRecords = $table.getUpdateRecords() VXETable.modal.alert(updateRecords.length) } findList() return { xTable, demo1, findList, validEvent, fullValidEvent, selectValidEvent, insertEvent, getInsertEvent, getRemoveEvent, getUpdateEvent } } })
后言
创作不易,要是本文章对广大读者有那么一点点帮助 不妨三连支持一下,您的鼓励就是博主创作的动力