Article directory
- Preface
- vxe-table
- Official website
- Implement table header drag and drop
- tree table
- Full keyboard operation
- Afterword
Foreword
hello world welcome to the new world of front-end
Current article series column: Front-end series of articles
?Bloggers still have a lot of knowledge and technology to master in the front-end field, and are constantly working hard to fill technical shortcomings. (If there is an error, thank you for pointing it out)
Thank you for your support! Your viewing is the motivation for the author’s creation
vxe-table
A UI component library specially used to perform complex operations on Vue3 tables, including virtual scrolling, row dragging of ordinary tables, full-screen display of tables, full keyboard operations of tables, disabled editing, etc.
Official website
Official website address
download
npm install xe-utils vxe-table
Configured in main.js or 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')
Realize table header dragging
Copy directly
<template> <div> <vxe-grid v-bind="gridOptions"> <template #toolbar_buttons> <vxe-button @click="gridOptions.align = 'left'">Left</vxe-button> <vxe-button @click="gridOptions.align = 'center'">Center</vxe-button> <vxe-button @click="gridOptions.align = 'right'">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>
Tree table
<template> <div> <vxe-toolbar> <template #buttons> <vxe-button @click="expandAllEvent">Expand all</vxe-button> <vxe-button @click="claseExpandEvent">Collapse all</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>
Full keyboard operation
template
<vxe-toolbar :refresh="{query: findList}"> <template #buttons> <vxe-button> <template #default>New operation</template> <template #dropdowns> <vxe-button type="text" @click="insertEvent(null)">Insert from the first row</vxe-button> <vxe-button type="text" @click="insertEvent(-1)">Insert from the end</vxe-button> <vxe-button type="text" @click="insertEvent($refs.xTable.getData(100))">Insert to row 100</vxe-button> <vxe-button type="text" @click="insertEvent($refs.xTable.getData(400))">Insert to row 400</vxe-button> </template> </vxe-button> <vxe-button> <template #default>Delete operation</template> <template #dropdowns> <vxe-button type="text" @click="$refs.xTable.removeCheckboxRow()">Remove check</vxe-button> <vxe-button type="text" @click="$refs.xTable.remove($refs.xTable.getData(0))">Remove the first row</vxe-button> <vxe-button type="text" @click="$refs.xTable.remove($refs.xTable.getData($refs.xTable.getData().length - 1))">Remove the last row</vxe- button> <vxe-button type="text" @click="$refs.xTable.remove($refs.xTable.getData(100))">Delete row 100</vxe-button> </template> </vxe-button> <vxe-button> <template #default>Verification operation</template> <template #dropdowns> <vxe-button type="text" @click="validEvent">Quick verification</vxe-button> <vxe-button type="text" @click="fullValidEvent">Full quick verification</vxe-button> <vxe-button type="text" @click="selectValidEvent">Selected row verification</vxe-button> </template> </vxe-button> <vxe-button @click="getInsertEvent">Get new</vxe-button> <vxe-button @click="getRemoveEvent">Get Removed</vxe-button> <vxe-button @click="getUpdateEvent">Get modifications</vxe-button> <vxe-button> <template #default>Scroll operation</template> <template #dropdowns> <vxe-button type="text" @click="$refs.xTable.scrollToRow($refs.xTable.getData(10))">Scroll to row 10</vxe-button> <vxe-button type="text" @click="$refs.xTable.scrollToRow($refs.xTable.getData(400))">Scroll row 400</vxe-button> <vxe-button type="text" @click="$refs.xTable.scrollToColumn($refs.xTable.getColumns(1))">Scroll column 1</vxe-button> <vxe-button type="text" @click="$refs.xTable.scrollToColumn($refs.xTable.getColumns(10))">Scroll column 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: 'Name must be between 3 and 50 characters long' } ], sex: [ {<!-- --> required: true, message: 'Gender must be filled in' } ] } as VxeTablePropTypes.ValidConfig }) const mockList = (size: number) => {<!-- --> const list: any[] = [] for (let index = 0; index < size; index ++ ) {<!-- --> list.push({<!-- --> checked: false, name: `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) // Block Vue from monitoring large arrays to avoid short-term lag caused by Vue binding big data. 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: 'Verification failed!' }) } else {<!-- --> VXETable.modal.message({<!-- --> status: 'success', content: 'Verification successful!' }) } } 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(`No. ${<!-- -->rowIndex + 1} row ${<!-- -->column.title} Verification error: ${<!-- -->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: 'Verification successful!' }) } } 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: 'Verification failed!' }) } else {<!-- --> VXETable.modal.message({<!-- --> status: 'success', content: 'Verification successful!' }) } } else {<!-- --> VXETable.modal.message({<!-- --> status: 'warning', content: 'No data selected!' }) } } 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 } } })
Afterword
Creation is not easy. If this article is of some help to readers, you may wish to support it three times. Your encouragement is the motivation for bloggers to create.