Vxe Table+Vue2封裝及使用方式
一、前言
在前端開(kāi)發(fā)中,表格展示數(shù)據(jù)是極為常見(jiàn)的需求。Vxe Table 作為一款功能強(qiáng)大的基于 Vue 的表格組件庫(kù),為我們高效構(gòu)建表格提供了諸多便利。
Vxe Table 具有豐富的特性,如支持復(fù)雜表頭、單元格編輯、數(shù)據(jù)校驗(yàn)、排序、篩選等。它擁有簡(jiǎn)潔易用的 API,能幫助開(kāi)發(fā)者快速搭建出符合業(yè)務(wù)需求的表格界面,大大提高開(kāi)發(fā)效率。其強(qiáng)大的自定義能力,可以滿足各種復(fù)雜場(chǎng)景下的表格展示需求。
二、Vxe Table 的封裝
1 安裝及引入流程見(jiàn)官網(wǎng)VxeTable v3
? 注意版本適配,Vue2對(duì)應(yīng)V3版本,Vue3對(duì)應(yīng)V4版本。
2 封裝自定義表格組件
? 在項(xiàng)目/src/components目錄下創(chuàng)建vxeTable目錄,新建一個(gè)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>
<!-- 自定義表格展開(kāi)內(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>
<!-- 分頁(yè)組件 -->
<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
},
// 分頁(yè)配置
pagination: {
type: Object,
default: null // 默認(rèn)不啟用分頁(yè)
}
},
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 } // 特殊配置單獨(dú)處理
}
const expiredAttribute = ['rowKey'] // 刪除過(guò)期屬性,避免傳入到vxe-grid組件報(bào)錯(cuò)
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)) // 特殊配置單獨(dú)處理
}
},
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>? 此外,為了方便使用,新建一個(gè)默認(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', // 表頭對(duì)齊方式
footerAlign: 'left', // 表尾對(duì)齊方式
keepSource: false, // 保持原始值的狀態(tài),被某些功能所依賴,比如編輯狀態(tài)、還原數(shù)據(jù)等
showOverflow: false, // 列超出寬度是否自動(dòng)省略,推薦每列自主設(shè)置 'false' 'true/ellipsis' 'title' 'tooltip'
showHeaderOverflow: 'title', // 表頭列超出寬度是否自動(dòng)省略
showFooterOverflow: 'title', // 表尾列超出寬度是否自動(dòng)省略
autoResize: true, // 是否自動(dòng)監(jiān)聽(tīng)父容器變化去重新計(jì)算表格(對(duì)于固定高度的表格,可能會(huì)用到)
resizeConfig: {
refreshDelay: 250 // 只對(duì) autoResize 有效,刷新延時(shí),當(dāng)父容器發(fā)生變化時(shí),至少多少毫秒刷新布局
},
columnConfig: {
isCurrent: false, // 鼠標(biāo)點(diǎn)擊列頭時(shí)是否高亮當(dāng)前列
isHover: false, // 鼠標(biāo)移到列時(shí)是否高亮當(dāng)前列
resizable: false // 是否允許拖動(dòng)列寬調(diào)整大小,推薦每列自主設(shè)置
},
rowConfig: {
// keyField: '_X_ROW_KEY', // 行數(shù)據(jù)的唯一主鍵字段名
isCurrent: false, // 當(dāng)鼠標(biāo)點(diǎn)擊行時(shí),是否要高亮當(dāng)前行
isHover: false // 當(dāng)鼠標(biāo)移到行時(shí),是否要高亮當(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: {
// 所有單元格開(kāi)啟工具提示 boolean
showAll: false,
// tooltip 的主題顏色string dark,light
theme: 'dark',
// 鼠標(biāo)是否可進(jìn)入到工具提示中boolean
enterable: false,
// 鼠標(biāo)移入后延時(shí)多少才顯示工具提示number
enterDelay: 500,
// 鼠標(biāo)移出后延時(shí)多少才隱藏工具提示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']
}
}? 在上述代碼中,我們通過(guò) props 接收外部傳遞的主要屬性(如:數(shù)據(jù)和表格列配置),其余屬性通過(guò)this.$attrs接收,父組件未設(shè)定的屬性值通過(guò)defaultConf進(jìn)行默認(rèn)配置。
實(shí)現(xiàn)了一個(gè)具有基本功能的可復(fù)用表格組件。同時(shí),綁定了一些常用的事件,如選擇項(xiàng)變化和行雙擊事件,并通過(guò)$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>
總計(jì):
<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)容 以下三種寫(xiě)法結(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>不用再看了,沒(méi)有更多數(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: '請(qǐng)輸入名字'
},
events: {
blur: (cellParams, targetParams) => {
console.log('name', targetParams.value)
}
}
}
// 格式化單元格
const formatSex = ({ cellValue }) => {
if (cellValue) {
return cellValue === '1' ? '男' : '女'
}
return ''
}
const cityOptions = [
{ label: '中華人民共和國(guó)廣東省深圳市龍崗區(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: '重置' }
]
}
}
]
}
/**
* 列常用配置說(shuō)明:
* 1. type:列類型,支持的類型有 seq(序號(hào))、checkbox(復(fù)選框)、radio(單選框)、expand(展開(kāi)行)、html(HTML片段)
* 2. field:列字段名
* 3. title:標(biāo)題名
* 4. width: 列寬,支持auto、固定像素、百分比、等比例分配等,如果不設(shè)置則按照表格的寬度進(jìn)行均勻分配。該表格組件支持min-width,可適時(shí)使用
* 5. 溢出省略:
* key的取值:showOverflow(單元格)、showHeaderOverflow(表頭) 和 showFooterOverflow(表尾)
* value的取值:ellipsis(省略號(hào))、title(省略號(hào) + 原生title)、tooltip(省略號(hào) + tooltip提示)
* 5. resizable: 是否允許拖動(dòng)列寬調(diào)整大小
* 6. fixed: 列固定,支持 left(固定左側(cè))、right(固定右側(cè))
* 7. align: 對(duì)齊方式,支持 left、center、right
* 8. sortable: 是否允許排序
* 9. filters: 篩選項(xiàng)。數(shù)組格式,元素結(jié)構(gòu):{ label: '選項(xiàng)', 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: '評(píng)分', 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: '書(shū)籍名稱', align: 'center' },
{ field: 'author', title: '作者', align: 'center' },
{ field: 'price', title: '價(jià)格', 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: `點(diǎn)擊了 ${ 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: '請(qǐng)?jiān)O(shè)置url.list屬性!'
// })
// return
// }
// 加載數(shù)據(jù),若傳入?yún)?shù)1則加載第一頁(yè)的內(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) {
// 計(jì)算需要生成的總數(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: '書(shū)籍名稱1', author: '作者1', price: 100 },
{ id: 1000000 + i + 2, name: '書(shū)籍名稱2', author: '作者2', price: 200 },
{ id: 1000000 + i + 3, name: '書(shū)籍名稱3', author: '作者3', price: 300 },
{ id: 1000000 + i + 4, name: '書(shū)籍名稱4', author: '作者4', price: 400 },
{ id: 1000000 + i + 5, name: '書(shū)籍名稱5', author: '作者5', price: 500 }
]
}
cacheList.push(item)
}
// 計(jì)算當(dāng)前頁(yè)數(shù)據(jù)的起始和結(jié)束索引
const startIndex = (page - 1) * rows
const endIndex = startIndex + rows
// 截取當(dāng)前頁(yè)的數(shù)據(jù)
const data = cacheList.slice(startIndex, endIndex)
resolve({
success: true,
data: {
records: data
}
})
}, 150)
})
}通過(guò)以上步驟,我們完成了在 Vue2 項(xiàng)目中對(duì) Vxe Table 的封裝及使用示例。
通過(guò)合理的封裝,能夠提高代碼的復(fù)用性和可維護(hù)性,更高效地實(shí)現(xiàn)項(xiàng)目中表格相關(guān)的功能需求。
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
vue將data恢復(fù)到初始狀態(tài) && 重新渲染組件實(shí)例
這篇文章主要介紹了vue將data恢復(fù)到初始狀態(tài) && 重新渲染組件實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-09-09
vue項(xiàng)目配置element-ui容易遇到的坑及解決
這篇文章主要介紹了vue項(xiàng)目配置element-ui容易遇到的坑及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-07-07
vue選項(xiàng)卡組件的實(shí)現(xiàn)方法
這篇文章主要為大家詳細(xì)介紹了vue選項(xiàng)卡組件的實(shí)現(xiàn)方法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-03-03
vue-cli 3如何使用vue-bootstrap-datetimepicker日期插件
這篇文章主要介紹了vue-cli 3如何使用vue-bootstrap-datetimepicker日期插件,幫助大家更好的理解和學(xué)習(xí)使用vue框架,感興趣的朋友可以了解下2021-02-02

