Vxe Table+Vue2封裝及使用方式
一、前言
在前端開發(fā)中,表格展示數(shù)據(jù)是極為常見的需求。Vxe Table 作為一款功能強大的基于 Vue 的表格組件庫,為我們高效構(gòu)建表格提供了諸多便利。
Vxe Table 具有豐富的特性,如支持復(fù)雜表頭、單元格編輯、數(shù)據(jù)校驗、排序、篩選等。它擁有簡潔易用的 API,能幫助開發(fā)者快速搭建出符合業(yè)務(wù)需求的表格界面,大大提高開發(fā)效率。其強大的自定義能力,可以滿足各種復(fù)雜場景下的表格展示需求。
二、Vxe Table 的封裝
1 安裝及引入流程見官網(wǎng)VxeTable v3
? 注意版本適配,Vue2對應(yīng)V3版本,Vue3對應(yīng)V4版本。
2 封裝自定義表格組件
? 在項目/src/components
目錄下創(chuàng)建vxeTable
目錄,新建一個index.js
和index.vue
。
代碼如下:
// index.js import VxeUIAll from 'vxe-pc-ui' import 'vxe-pc-ui/lib/style.css' import VxeUITable from 'vxe-table' import 'vxe-table/lib/style.css' export const CustomVxeTable = (app) => { app.use(VxeUIAll) app.use(VxeUITable) }
<template> <!-- 表格組件 --> <vxe-grid ref="vxeTable" v-bind="gridOptions" v-on="$listeners" :data="dataSource" :columns="columns" :border="bordered" > <!-- 自定義表單內(nèi)容 --> <template #form> <slot name="form"></slot> </template> <!-- 自定義表格上方內(nèi)容 --> <template #top> <slot name="top"></slot> </template> <!-- 自定義表頭內(nèi)容 --> <template v-for="header in slotsHeader" #[header]> <slot :name="header"></slot> </template> <!-- 自定義表格展開內(nèi)容 --> <template #expandedRowRender="{ row }"> <slot name="expandedRowRender" :record="row"></slot> </template> <!-- 自定義表格內(nèi)容 --> <template v-for="slot in slotsDefault" #[slot]="{ row }"> <slot :name="slot" :text="row[slot]" :record="row"></slot> </template> <!-- 自定義空數(shù)據(jù)內(nèi)容 --> <template #empty> <slot v-if="$slots.empty" name="empty"></slot> <a-empty v-else /> </template> <!-- 自定義表格下方內(nèi)容 --> <template #bottom> <slot name="bottom"></slot> </template> <!-- 分頁組件 --> <template #pager> <vxe-pager v-if="pagination" :loading="gridOptions.loading" :loyouts="pagerOptions.loyouts" :size="pagerOptions.size" :currentPage.sync="pagerOptions.current" :pageSize.sync="pagerOptions.pageSize" :pageSizes="pagerOptions.pageSizes" :total="pagerOptions.total" @page-change="handlePageChange"> </vxe-pager> </template> </vxe-grid> </template> <script> import defaultConf from './defaultConf' /** * 根據(jù)插槽類型獲取插槽列表 * @param columns 列配置 * @param slotType 插槽類型 * @returns {*[]} */ function slotsByType(columns, slotType) { const slots = [] const findSlots = (column) => { if (!column) return if (column.slots && column.slots[slotType]) { slots.push(column.slots[slotType]) } if (column.children) { for (let child of column.children) { findSlots(child) } } } for (let column of columns) { findSlots(column) } return slots } export default { name: 'VxeTable', props: { // 表格數(shù)據(jù) dataSource: { type: Array, required: true }, // 表格列配置 columns: { type: Array, required: true }, // 邊框 bordered: { type: Boolean, default: true }, // 分頁配置 pagination: { type: Object, default: null // 默認(rèn)不啟用分頁 } }, data() { return {} }, computed: { gridOptions() { const gridOptions = { ...defaultConf.grid, // 默認(rèn)配置 ...this.$attrs, // 用戶傳入的配置 ...this.props, // props傳入的配置 rowConfig: { ...defaultConf.rowConfig, useKey: Boolean(this.$attrs.rowKey), keyField: this.$attrs.rowKey } // 特殊配置單獨處理 } const expiredAttribute = ['rowKey'] // 刪除過期屬性,避免傳入到vxe-grid組件報錯 for (let attr of expiredAttribute) { delete gridOptions[attr] } return gridOptions }, pagerOptions() { if (!this.pagination) return {} return { ...defaultConf.pager, // 默認(rèn)配置 ...this.pagination, // 用戶傳入的配置 pageSizes: this.pagination.pageSizeOptions.map(item => parseInt(item)) // 特殊配置單獨處理 } }, slotsDefault() { return slotsByType(this.columns, 'default') }, slotsHeader() { return slotsByType(this.columns, 'header') } }, mounted() { // 將子組件的方法復(fù)制到父組件 Object.keys(this.$refs.vxeTable.$options.methods).forEach(method => { this[method] = this.$refs.vxeTable[method].bind(this.$refs.vxeTable) }) }, methods: { handlePageChange({ currentPage, pageSize }) { this.$emit('change', { ...this.pagination, current: currentPage, pageSize: pageSize }) } } } </script> <style scoped> /* 可以根據(jù)需要添加樣式 */ </style>
? 此外,為了方便使用,新建一個默認(rèn)配置文件defaultConf.js
。
export default { grid: { layouts: ['Form', 'Toolbar', 'Top', 'Table', 'Bottom', 'Pager'], height: null, // %, px minHeight: null, maxHeight: null, stripe: true, // 斑馬紋 border: true, // 邊框 round: false, // 圓角邊框 size: 'small', // medium, small, mini showHeader: true, // 是否顯示表頭 showFooter: false, // 是否顯示表尾 headerAlign: 'center', // 表頭對齊方式 footerAlign: 'left', // 表尾對齊方式 keepSource: false, // 保持原始值的狀態(tài),被某些功能所依賴,比如編輯狀態(tài)、還原數(shù)據(jù)等 showOverflow: false, // 列超出寬度是否自動省略,推薦每列自主設(shè)置 'false' 'true/ellipsis' 'title' 'tooltip' showHeaderOverflow: 'title', // 表頭列超出寬度是否自動省略 showFooterOverflow: 'title', // 表尾列超出寬度是否自動省略 autoResize: true, // 是否自動監(jiān)聽父容器變化去重新計算表格(對于固定高度的表格,可能會用到) resizeConfig: { refreshDelay: 250 // 只對 autoResize 有效,刷新延時,當(dāng)父容器發(fā)生變化時,至少多少毫秒刷新布局 }, columnConfig: { isCurrent: false, // 鼠標(biāo)點擊列頭時是否高亮當(dāng)前列 isHover: false, // 鼠標(biāo)移到列時是否高亮當(dāng)前列 resizable: false // 是否允許拖動列寬調(diào)整大小,推薦每列自主設(shè)置 }, rowConfig: { // keyField: '_X_ROW_KEY', // 行數(shù)據(jù)的唯一主鍵字段名 isCurrent: false, // 當(dāng)鼠標(biāo)點擊行時,是否要高亮當(dāng)前行 isHover: false // 當(dāng)鼠標(biāo)移到行時,是否要高亮當(dāng)前行 }, cellConfig: { padding: true // 是否顯示間距 // height: 48, // number, 默認(rèn)單元格高度 }, editConfig: { // mode: 'cell', // cell, row trigger: 'click', showIcon: true, showAsterisk: true }, radioConfig: { // trigger: 'default' strict: true }, checkboxConfig: { // trigger: 'default', strict: true }, tooltipConfig: { // 所有單元格開啟工具提示 boolean showAll: false, // tooltip 的主題顏色string dark,light theme: 'dark', // 鼠標(biāo)是否可進(jìn)入到工具提示中boolean enterable: false, // 鼠標(biāo)移入后延時多少才顯示工具提示number enterDelay: 500, // 鼠標(biāo)移出后延時多少才隱藏工具提示number leaveDelay: 300 }, validConfig: { showMessage: true, autoClear: true, autoPos: true, message: 'inline', msgMode: 'single' }, menuConfig: { enabled: false // 是否啟用 }, customConfig: { allowVisible: true, allowResizable: true, allowFixed: true, allowSort: true, showFooter: true, placement: 'topRight', // storage: false, // checkMethod () {}, modalOptions: { showZoom: true, mask: true, lockView: true, resize: true, escClosable: true } }, sortConfig: { // remote: false, // trigger: 'default', // orders: ['asc', 'desc', null], // sortMethod: null, showIcon: true, iconLayout: 'vertical' }, filterConfig: { // remote: false, // filterMethod: null, showIcon: true }, treeConfig: { rowField: 'id', parentField: 'parentId', childrenField: 'children', hasChildField: 'hasChild', indent: 20, showIcon: true, expandInit: false }, expandConfig: { // trigger: 'default', showIcon: true }, importConfig: { _typeMaps: { csv: 1, html: 1, xml: 1, txt: 1 }, modes: ['insert', 'covering'] }, exportConfig: { _typeMaps: { csv: 1, html: 1, xml: 1, txt: 1 }, modes: ['current', 'selected'] }, printConfig: { modes: ['current', 'selected'] }, mouseConfig: { extension: true }, keyboardConfig: { isEsc: true }, scrollX: { // enabled: false, gt: 60 // oSize: 0 }, scrollY: { // enabled: false, gt: 100 // oSize: 0 } }, pager: { loyouts: ['Home', 'PrevJump', 'PrevPage', 'Number', 'NextPage', 'NextJump', 'End', 'Sizes', 'FullJump', 'Total'] } }
? 在上述代碼中,我們通過 props 接收外部傳遞的主要屬性(如:數(shù)據(jù)和表格列配置),其余屬性通過this.$attrs
接收,父組件未設(shè)定的屬性值通過defaultConf
進(jìn)行默認(rèn)配置。
實現(xiàn)了一個具有基本功能的可復(fù)用表格組件。同時,綁定了一些常用的事件,如選擇項變化和行雙擊事件,并通過$emit將事件傳遞給父組件。
三、Vxe Table 的使用示例
在父組件中引入并使用封裝的表格組件
在需要使用表格的父組件中,引入MyTable.vue組件,并傳遞相應(yīng)的數(shù)據(jù)和配置。
<template> <div class="demo-page-wrapper"> <!-- 使用二次封裝的 VxeTable 組件 --> <div style="padding: 16px 0; display: flex;align-items: center;justify-content: space-between;"> <a-space size="middle"> <a-button @click="sortEvent('age', 'asc')">年齡 升序</a-button> <a-button @click="sortEvent('age', 'desc')">年齡 降序</a-button> <a-button @click="clearSortEvent" type="primary">清除排序</a-button> </a-space> <a-space size="middle"> <div> 總計: <span>1000</span> 元 </div> <a-button @click="getSelectEvent" type="primary">獲取選中數(shù)據(jù)</a-button> <a-button @click="handleExport" type="primary">導(dǎo)出</a-button> </a-space> </div> <VxeTable ref="table" size="small" rowKey="id" border round stripe height="auto" :expandConfig="{ showIcon: false }" :loading="loading" :dataSource="dataSource" :columns="cols" :pagination="ipagination" :menuConfig="menuConfig" @cell-menu="cellMenuEvent" @menu-click="menuClickEvent" @cell-click="handleCellClick" @edit-closed="handleEditClosed" @change="handleTableChange" @form-submit="formSubmitEvent" @form-reset="formResetEvent" > <!-- 自定義表頭內(nèi)容 --> <template #name_header> <span>《名字名字名字名字名字》</span> </template> <template #expandedRowRender="{ record }"> <vxe-grid :columns="childCols" :data="record.bookList"></vxe-grid> </template> <!-- 自定義表格內(nèi)容 以下三種寫法結(jié)果相同 --> <!-- <template v-slot:email="{ record }">--> <!-- <template #email="{ text,record }">--> <template slot="email" slot-scope="{ text,record }"> {{ text }} <vxe-text :content="record.email" click-to-copy></vxe-text> </template> <template #action="{ record }"> <a @click="handleEdit(record)">編輯</a> </template> <!-- 自定義空數(shù)據(jù)內(nèi)容 --> <template #empty> <span style="color: red;"> <img src="https://vxeui.com/resource/img/546.gif"> <p>不用再看了,沒有更多數(shù)據(jù)了?。。。?!</p> </span> </template> </VxeTable> </div> </template> <script> import XEUtils from 'xe-utils' import VxeTable from '@/components/VxeTable/Index.vue' import GridMixin from '@/mixins/GridMixin' import { loadMockData } from '@views/demo/vxeTable/generateData' import { VxeUI } from 'vxe-table' // 自定義單元格渲染 const avatarUrlCellRender = { name: 'VxeImage', props: { circle: true, width: 36, height: 36 } } const levelNumCellRender = { name: 'VxeRate', props: { readonly: false } } const flagCellRender = { name: 'VxeSwitch', props: { readonly: false }, events: { change: (cellParams, targetParams) => { console.log('flag', targetParams.value, cellParams) } } } const nameEditRender = { name: 'VxeInput', props: { trim: true, clearable: true, maxLength: 5, placeholder: '請輸入名字' }, events: { blur: (cellParams, targetParams) => { console.log('name', targetParams.value) } } } // 格式化單元格 const formatSex = ({ cellValue }) => { if (cellValue) { return cellValue === '1' ? '男' : '女' } return '' } const cityOptions = [ { label: '中華人民共和國廣東省深圳市龍崗區(qū)人民法院', value: 'sz' }, { label: '廣東省廣州市', value: 'gz' }, { label: '北京市', value: 'bj' }, { label: '上海市', value: 'sh' }, { label: '浙江省杭州市', value: 'hz' } ] const formatCity = ({ cellValue }) => { const item = cityOptions.find(item => item.value === cellValue) return item ? item.label : cellValue } const formatAmount = ({ cellValue }) => { if (cellValue) { return `¥${ XEUtils.commafy(cellValue, { digits: 2 }) }` } return '' } // 篩選條件 const sexFilterOptions = [ { label: '女', value: '0' }, { label: '男', value: '1' } ] const ageFilterOptions = [ { label: '(18,25]', value: '18-25' }, { label: '(26,35]', value: '26-35' }, { label: '(36,45]', value: '36-45' }, { label: '(46,55]', value: '46-55' }, { label: '(56,65]', value: '56-65' } ] const ageFilterMethod = function({ value: filterVal, cellValue }) { filterVal = filterVal.split('-') const age = parseInt(cellValue) if (filterVal.length === 2) { return age >= parseInt(filterVal[0]) && age < parseInt(filterVal[1]) } } // 右鍵菜單 const menuConfig = { header: { options: [ [ { code: 'exportAll', name: '導(dǎo)出所有.csv', prefixConfig: { icon: 'vxe-icon-download' }, visible: true, disabled: false } ] ] }, body: { options: [ [ { code: 'copy', name: '復(fù)制內(nèi)容(Ctrl+C)', prefixConfig: { icon: 'vxe-icon-copy' }, visible: true, disabled: false }, { code: 'clear', name: '清除內(nèi)容', visible: true, disabled: false }, { code: 'reload', name: '刷新表格', visible: true, disabled: false } ], [ { code: 'fixed', name: '凍結(jié)列', children: [ { code: 'cancelFixed', name: '取消凍結(jié)' }, { code: 'fixedLeft', name: '凍結(jié)在左側(cè)', prefixConfig: { icon: 'vxe-icon-fixed-left' } }, { code: 'fixedRight', name: '凍結(jié)在右側(cè)', prefixConfig: { icon: 'vxe-icon-fixed-right' } } ] } ], [ { code: 'myPrint', name: '打印(Ctrl+P)', prefixConfig: { icon: 'vxe-icon-print' }, visible: true, disabled: false }, { code: 'myExport', name: '導(dǎo)出.csv', prefixConfig: { icon: 'vxe-icon-download' }, visible: true, disabled: false } ] ] } } const formConfig = { data: { name: '', role: '', sex: '', num: '', address: '' }, items: [ { field: 'name', title: '名稱', span: 8, itemRender: { name: 'VxeInput' } }, { field: 'email', title: '郵件', span: 8, itemRender: { name: 'VxeInput' } }, { field: 'nickname', title: '昵稱', span: 8, itemRender: { name: 'VxeInput' } }, { field: 'role', title: '角色', span: 8, folding: true, itemRender: { name: 'VxeInput' } }, { field: 'sex', title: '性別', span: 8, folding: true, itemRender: { name: 'VxeInput' } }, { field: 'age', title: '年齡', span: 8, folding: true, itemRender: { name: 'VxeInput' } }, { span: 24, collapseNode: true, align: 'center', itemRender: { name: 'VxeButtonGroup', options: [ { type: 'submit', content: '搜索', status: 'primary' }, { type: 'reset', content: '重置' } ] } } ] } /** * 列常用配置說明: * 1. type:列類型,支持的類型有 seq(序號)、checkbox(復(fù)選框)、radio(單選框)、expand(展開行)、html(HTML片段) * 2. field:列字段名 * 3. title:標(biāo)題名 * 4. width: 列寬,支持auto、固定像素、百分比、等比例分配等,如果不設(shè)置則按照表格的寬度進(jìn)行均勻分配。該表格組件支持min-width,可適時使用 * 5. 溢出省略: * key的取值:showOverflow(單元格)、showHeaderOverflow(表頭) 和 showFooterOverflow(表尾) * value的取值:ellipsis(省略號)、title(省略號 + 原生title)、tooltip(省略號 + tooltip提示) * 5. resizable: 是否允許拖動列寬調(diào)整大小 * 6. fixed: 列固定,支持 left(固定左側(cè))、right(固定右側(cè)) * 7. align: 對齊方式,支持 left、center、right * 8. sortable: 是否允許排序 * 9. filters: 篩選項。數(shù)組格式,元素結(jié)構(gòu):{ label: '選項', value: '值' ,checked:'是否默認(rèn)選中'}。搭配filterMethod定義篩選方法,filterMultiple定義是否多選 * 10. formatter: (({ cellValue, row, column }) => string) | any[] | string,格式化顯示內(nèi)容 * 11. cellRender: 自定義單元格渲染 * 12. editRender: 自定義編輯渲染 * 13. contentRender: 自定義內(nèi)容渲染 * 13. slots: 自定義插槽 */ const cols = [ { type: 'expand', width: '40px', align: 'center', slots: { content: 'expandedRowRender' } }, { field: 'seq', type: 'seq', width: '40px', align: 'center', resizable: false }, { field: 'checkbox', type: 'checkbox', width: '40px', align: 'center' }, { field: 'avatarUrl', title: '頭像', width: '80px', align: 'center', titlePrefix: { content: '自定義前綴圖標(biāo)', icon: 'vxe-icon-question-circle-fill' }, cellRender: avatarUrlCellRender }, { field: 'name', title: '名字', align: 'center', showHeaderOverflow: 'ellipsis', minWidth: '100px', dragSort: true, editRender: nameEditRender, slots: { header: 'name_header' } }, { title: '基本信息', field: 'info', children: [ { field: 'city', title: '所在地', width: '250px', showOverflow: 'tooltip', formatter: formatCity }, { field: 'age', title: '年齡', width: '100px', align: 'center', sortable: true, filters: ageFilterOptions, filterMethod: ageFilterMethod, editRender: { name: 'input', attrs: { type: 'number' } } }, { field: 'sex', title: '性別', width: '60px', align: 'center', formatter: formatSex, filters: sexFilterOptions, filterMultiple: true, editRender: { name: 'select', options: sexFilterOptions } }, { field: 'email', title: '郵箱', width: '220px', slots: { default: 'email' } } ] }, { field: 'flag', title: '是否啟用', width: '80px', align: 'center', cellRender: flagCellRender }, { field: 'levelNum', title: '評分', width: '200px', align: 'center', cellRender: levelNumCellRender }, { title: '年度賬單', field: 'annualStatement', children: [ { field: 'annualStatement.m1', title: '一月', width: '140px', formatter: formatAmount }, { field: 'annualStatement.m2', title: '二月', width: '140px', formatter: formatAmount }, { field: 'annualStatement.m3', title: '三月', width: '140px', formatter: formatAmount }, { field: 'annualStatement.m4', title: '四月', width: '140px', formatter: formatAmount }, { field: 'annualStatement.m5', title: '五月', width: '140px', formatter: formatAmount }, { field: 'annualStatement.m6', title: '六月', width: '140px', formatter: formatAmount }, { field: 'annualStatement.m7', title: '七月', width: '140px', formatter: formatAmount }, { field: 'annualStatement.m8', title: '八月', width: '140px', formatter: formatAmount }, { field: 'annualStatement.m9', title: '九月', width: '140px', formatter: formatAmount }, { field: 'annualStatement.m10', title: '十月', width: '140px', formatter: formatAmount }, { field: 'annualStatement.m11', title: '十一月', width: '140px', formatter: formatAmount }, { field: 'annualStatement.m12', title: '十二月', width: '140px', formatter: formatAmount } ] }, { title: '操作', field: 'action', width: '100px', align: 'center', fixed: 'right', slots: { default: 'action' } } ] const childCols = [ { field: 'name', title: '書籍名稱', align: 'center' }, { field: 'author', title: '作者', align: 'center' }, { field: 'price', title: '價格', align: 'center' } ] export default { components: { VxeTable }, mixins: [GridMixin], data() { return { cols, childCols, menuConfig, formConfig, disableMixinCreated: true } }, mounted() { this.loadData() }, methods: { formSubmitEvent() { console.log('form submit') }, formResetEvent() { console.log('form reset') }, cellMenuEvent({ row }) { const $grid = this.$refs.table if ($grid) { $grid.setCurrentRow(row) } }, menuClickEvent({ menu, row, column }) { const $grid = this.$refs.table if ($grid) { switch (menu.code) { case 'copy': if (row && column) { if (VxeUI.clipboard.copy(row[column.field])) { VxeUI.modal.message({ content: '已復(fù)制到剪貼板!', status: 'success' }) } } break case 'clear': $grid.clearData(row, column.field) break case 'myPrint': $grid.print() break case 'myExport': $grid.exportData() break default: VxeUI.modal.message({ content: `點擊了 ${ menu.code }`, status: 'success' }) break } } }, handleExport() { const $grid = this.$refs.table if ($grid) { $grid.openExport() } }, getSelectEvent() { const $table = this.$refs.table if ($table) { const selectRecords = $table.getCheckboxRecords() console.log('選中數(shù)據(jù):', selectRecords) } }, sortEvent(field, order) { const $table = this.$refs.table if ($table) { $table.sort({ field, order }) } }, clearSortEvent() { const $table = this.$refs.table if ($table) { $table.clearSort() } }, handleEdit(record) { console.log('Edit:', record) this.$refs.table.setEditRow(record) }, loadData(arg) { // if (!this.url.list) { // this.$message.error({ // key: this.messageKey, // content: '請設(shè)置url.list屬性!' // }) // return // } // 加載數(shù)據(jù),若傳入?yún)?shù)1則加載第一頁的內(nèi)容 if (arg === 1) { if (false != this.ipagination) { this.ipagination.current = 1 } } this.selectedRowKeys = [] this.selectedRows = [] // 查詢條件 let params = this.getQueryParams() this.loading = true // get(this.url.list, params).then(res=> { loadMockData(this.ipagination.current, this.ipagination.pageSize).then(res => { if (res.success) { if (this.rowKey) { this.initRowKey(res.data.records) } this.dataSource = res.data.records if (false !== this.ipagination) { if (this.dataSource.length <= 0 && this.ipagination.current > 1) { this.ipagination.current-- this.loadData() return } else if (this.dataSource.length > 0 && this.ipagination.current < 1) { this.ipagination.current = 1 } this.ipagination.total = 100 } this.loadDataSuccess() } else { this.$message.warning({ key: this.messageKey, content: (res.msg && res.msg !== '操作成功' ? res.msg : '操作失??!') }) } // setTimeout(() => { this.loading = false // }, 5000) }) }, handleEditClosed(params) { const { row, rowIndex, column, columnIndex } = params console.log('Row edit closed:(' + rowIndex + ', ' + columnIndex + ')', row, row[column.field]) }, handleCellClick(params) { console.log('Cell click:', params) } } } </script> <style scoped> /* 可以根據(jù)需要添加樣式 */ .demo-page-wrapper { height: calc(100vh - 158px); } </style>
附件:模擬數(shù)據(jù)生成方法js文件generateData.js
import XEUtils from 'xe-utils' const arList = XEUtils.shuffle(XEUtils.range(1, 21).map(num => `https://vxeui.com/resource/avatarImg/avatar${ num }.jpeg`)) const neList = XEUtils.shuffle(['張三', '李四', '王五', '小徐', '老張', '老六', '小明', '老徐', '小張', '小趙', '老高', '老鐵', '趙高', '小王', '老王']) const cyList = XEUtils.shuffle(['sz', 'gz', 'bj', 'sh', 'hz']) const sxList = XEUtils.shuffle(XEUtils.range(1, 60).map(num => `${ num % 2 }`)) const aeList = XEUtils.shuffle(XEUtils.range(18, 66)) const elList = XEUtils.range(1, 60).map(() => `${ XEUtils.sample('qwertyuiopasdfghjklzxcvbnm'.split(''), XEUtils.random(6, 16)).join('') }@163.com`) const lnList = XEUtils.shuffle(XEUtils.range(0, 5)) const asmMpas = { m1: XEUtils.shuffle(XEUtils.range(1000, 1500)), m2: XEUtils.shuffle(XEUtils.range(1100, 1400)), m3: XEUtils.shuffle(XEUtils.range(800, 1200)), m4: XEUtils.shuffle(XEUtils.range(3000, 3600)), m5: XEUtils.shuffle(XEUtils.range(2000, 2100)), m6: XEUtils.shuffle(XEUtils.range(1600, 1700)), m7: XEUtils.shuffle(XEUtils.range(1200, 1300)), m8: XEUtils.shuffle(XEUtils.range(1100, 1200)), m9: XEUtils.shuffle(XEUtils.range(1700, 1800)), m10: XEUtils.shuffle(XEUtils.range(1300, 1700)), m11: XEUtils.shuffle(XEUtils.range(1000, 1300)), m12: XEUtils.shuffle(XEUtils.range(800, 1200)) } const fgList = XEUtils.shuffle(XEUtils.range(1, 60).map(num => (num % 2) === 0)) const cacheList = [] export function loadMockData(page, rows) { // 計算需要生成的總數(shù)據(jù)量 const rSize = page * rows return new Promise(resolve => { setTimeout(() => { // 生成足夠的數(shù)據(jù)到 cacheList for (let i = cacheList.length; i < rSize; i++) { const item = { id: 1000000 + i, name: neList[i % neList.length], nickname: '', sex: sxList[i % sxList.length], age: aeList[i % aeList.length], email: elList[i % elList.length], city: cyList[i % cyList.length], avatarUrl: arList[i % arList.length], levelNum: lnList[i % lnList.length], annualStatement: { m1: asmMpas.m1[i % asmMpas.m1.length], m2: asmMpas.m2[i % asmMpas.m2.length], m3: asmMpas.m3[i % asmMpas.m3.length], m4: asmMpas.m4[i % asmMpas.m4.length], m5: asmMpas.m5[i % asmMpas.m5.length], m6: asmMpas.m6[i % asmMpas.m6.length], m7: asmMpas.m7[i % asmMpas.m7.length], m8: asmMpas.m8[i % asmMpas.m8.length], m9: asmMpas.m9[i % asmMpas.m9.length], m10: asmMpas.m10[i % asmMpas.m10.length], m11: asmMpas.m11[i % asmMpas.m11.length], m12: asmMpas.m12[i % asmMpas.m12.length] }, flag: fgList[i % fgList.length], bookList: [ { id: 1000000 + i + 1, name: '書籍名稱1', author: '作者1', price: 100 }, { id: 1000000 + i + 2, name: '書籍名稱2', author: '作者2', price: 200 }, { id: 1000000 + i + 3, name: '書籍名稱3', author: '作者3', price: 300 }, { id: 1000000 + i + 4, name: '書籍名稱4', author: '作者4', price: 400 }, { id: 1000000 + i + 5, name: '書籍名稱5', author: '作者5', price: 500 } ] } cacheList.push(item) } // 計算當(dāng)前頁數(shù)據(jù)的起始和結(jié)束索引 const startIndex = (page - 1) * rows const endIndex = startIndex + rows // 截取當(dāng)前頁的數(shù)據(jù) const data = cacheList.slice(startIndex, endIndex) resolve({ success: true, data: { records: data } }) }, 150) }) }
通過以上步驟,我們完成了在 Vue2 項目中對 Vxe Table 的封裝及使用示例。
通過合理的封裝,能夠提高代碼的復(fù)用性和可維護(hù)性,更高效地實現(xiàn)項目中表格相關(guān)的功能需求。
總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
vue將data恢復(fù)到初始狀態(tài) && 重新渲染組件實例
這篇文章主要介紹了vue將data恢復(fù)到初始狀態(tài) && 重新渲染組件實例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-09-09vue-cli 3如何使用vue-bootstrap-datetimepicker日期插件
這篇文章主要介紹了vue-cli 3如何使用vue-bootstrap-datetimepicker日期插件,幫助大家更好的理解和學(xué)習(xí)使用vue框架,感興趣的朋友可以了解下2021-02-02