-
后端返回数据:后端返回一千条数据给前端。你可以在后端将这些数据分成若干组,每组包含一定数量的数据。
-
前端定时器渲染数据:前端使用定时器来逐批次渲染数据,以避免一次性渲染大量数据导致页面卡顿。
下面是一个简单的示例代码,演示了如何在Vue 2中实现定时器分批次渲染数据的功能(不包含合并表格),并自定义分页的前进后退:
<template>
<div>
<ul>
<li v-for="item in currentBatch" :key="item.id">{{ item.text }}</li>
</ul>
<button @click="previousPage" :disabled="currentPage === 1">Previous Page</button>
<button @click="nextPage" :disabled="currentPage * pageSize >= templeList.length">Next Page</button>
</div>
</template>
<script>
export default {
data() {
return {
templeList: [], // 后端返回的所有数据
pageSize: 10, // 每页显示的数据量
currentPage: 1, // 当前页数
currentBatch: [], // 当前页要渲染的数据
timer: null // 定时器
};
},
mounted() {
// 模拟后端返回的一千条数据
for (let i = 0; i < 1000; i++) {
this.templeList.push({ id: i + 1, text: `Item ${i + 1}` });
}
// 初始化渲染第一页数据
this.renderPage(this.currentPage);
},
beforeDestroy() {
// 清除定时器
clearInterval(this.timer);
},
methods: {
renderPage(page) {
const startIndex = (page - 1) * this.pageSize;
const endIndex = startIndex + this.pageSize;
this.currentBatch = this.templeList.slice(startIndex, endIndex);
// 清除之前的定时器
clearInterval(this.timer);
// 开始定时器渲染数据
let index = 0;
this.timer = setInterval(() => {
if (index < this.currentBatch.length) {
this.currentBatch = this.currentBatch.slice(0, index + 1);
index++;
} else {
clearInterval(this.timer);
}
}, 1000); // 每隔1秒渲染一条数据
},
nextPage() {
if (this.currentPage * this.pageSize < this.templeList.length) {
this.currentPage++;
this.renderPage(this.currentPage);
}
},
previousPage() {
if (this.currentPage > 1) {
this.currentPage--;
this.renderPage(this.currentPage);
}
}
}
};
</script>
使用最简单的代码呈现的,大家可以根据自己不同的情况来实际应用,我是因为数据量过大时el-table表格合并特别卡,所以自定义分页。以下为个人实际应用代码 用于存档 便于以后查看
实现效果
data() {
return {
tableList: [],
newTableList: [], // 处理跨行用数据
templeList: [], // 列表原始数据
columnKey: [ // 每一列的跨行key
'customerId',
'customerId',
'customerId',
'chargesType',
'meterFlow',
'chargesType',
'unitPrice',
'feeAmount',
'customerId',
'customerId',
'customerId',
'customerId',
'customerId'
],
displayedItems: [], // 当前展示的数据
timer: null, // 定时器
pageSize: 10, // 每页显示的数据量
currentPage: 1, // 当前页数
currentBatch: [] // 当前页要渲染的数据
}
},
methods:{
// 处理表格跨行
spanArry(key) {
const rowspans = []
var pro = 0 // 下标
this.newTableList.forEach((item, index) => {
if (index === 0) {
rowspans.push(1)
pro = 0
} else {
if (item[key] === this.newTableList[index - 1][key]) {
// 当前项和前一项比较
rowspans[pro] += 1
rowspans.push(0)
} else {
rowspans.push(1)
pro = index
}
}
})
return rowspans
},
// 当前行row、当前列column、当前行号rowIndex、当前列号columnIndex
objectSpanMethod({ row, column, rowIndex, columnIndex }) {
// 能源用量 计费 单价 能源金额 不需要跨行
if (columnIndex === 3 || columnIndex === 4 || columnIndex === 5 || columnIndex === 6 || columnIndex === 7) {
return {
rowspan: 1,
colspan: 1
}
} else {
return {
rowspan: this.spanArry(this.columnKey[columnIndex])[rowIndex],
colspan: 1
}
}
},
// 获取后端的无分页数据--树形结构
postPreviewAdd(accountPeriod, customerIdList) {
this.accountPeriod = accountPeriod
this.customerIdList = customerIdList
this.isLoading = true
POST_WATERBILLING_ADDPREVIEW(accountPeriod, customerIdList).then(
(res) => {
if (res) {
this.templeList = res.previewinfoList // 留存初始数据
this.renderPage(this.currentPage) // 初始化渲染第一页数据
}
}
)
this.isLoading = false
},
// 定时器
renderPage(page) {
console.log('走这了吗')
const startIndex = (page - 1) * this.pageSize
const endIndex = startIndex + this.pageSize
this.currentBatch = this.templeList.slice(startIndex, endIndex)
this.getTableList(this.currentBatch) // 调取将数组扁平化方法将拿来的十条数据平铺
// 清除之前的定时器
clearInterval(this.timer)
// 开始定时器渲染数据
let index = 0
this.timer = setInterval(() => {
if (index < this.currentBatch.length) {
this.currentBatch = this.currentBatch.slice(0, index + 1)
index++
} else {
clearInterval(this.timer)
}
}, 1000) // 每隔1秒渲染一条数据
},
// 处理树形表格扁平化
getTableList(previewinfoList) {
let list = []
if (previewinfoList.length > 0) {
previewinfoList.forEach((element) => {
// meteringfeeList 能源分类
if (element.meteringfeeList) {
element.meteringfeeList.forEach((child) => {
// feeinfoList 阶梯计费
if (child.feeinfoList) {
child.feeinfoList.forEach((three) => {
// eslint-disable-next-line no-unused-vars
const { meteringfeeList, ...p } = element
var obj = {}
obj = Object.assign({}, p, child, three)
list.push(obj)
})
}
})
} else if (!element.meteringfeeList) {
// feeinfoList 阶梯计费
list = previewinfoList
} else {
// eslint-disable-next-line no-unused-vars
const { meteringfeeList, ...p } = element
var obj = {}
var obj2 = {
curMeterflow: '',
feeAmount: '',
preMeterflow: '',
subdivisionType: '',
subdivisionTypeText: '',
useMeterflow: '',
chargesType: '',
chargesTypeName: '',
meterFlow: '',
unitPrice: ''
}
obj = Object.assign({}, p, obj2)
list.push(obj)
}
})
console.log('合并后', list)
this.newTableList = list// 合并表格用
this.tableList = list // 拼接所有数据
}
return list
},
// 下一页按钮
nextPage(e) {
if (this.currentPage * this.pageSize < this.templeList.length) {
this.currentPage++
this.renderPage(this.currentPage)
}
},
// 上一页按钮
previousPage() {
if (this.currentPage > 1) {
this.currentPage--
this.renderPage(this.currentPage)
}
},
}
// ----------------html部分-----------------
<el-table ref="tableRef" :data="tableList" class="users-table" border :span-method="objectSpanMethod" highlight-current-row height="72vh">
<el-table-column align="center" label="企业名称" min-width="240px" prop="customerName" show-overflow-tooltip />
<el-table-column align="center" label="账期" show-overflow-tooltip prop="accountPeriod" />
<el-table-column align="center" label="能源类型" show-overflow-tooltip>
<template slot-scope="scope">
{{ getEnumLabelStr("MajorEnum", scope.row.major) }}
</template>
</el-table-column>
<el-table-column align="center" label="能源分类" show-overflow-tooltip prop="subdivisionTypeText" min-width="180px" />
<el-table-column align="center" label="能源用量(吨)" show-overflow-tooltip prop="meterFlow" min-width="120px" />
<el-table-column align="center" label="计费类型" show-overflow-tooltip prop="chargesTypeName" min-width="100px" />
<el-table-column align="center" label="单价(元)" show-overflow-tooltip prop="unitPrice" min-width="100px" />
<el-table-column align="center" label="能源金额(元)" show-overflow-tooltip prop="feeAmount" min-width="140px" />
<el-table-column align="center" label="消防水系统运行管理费(元)" min-width="250px" show-overflow-tooltip prop="manageFeeAmount" />
<el-table-column align="center" label="出账总金额(元)" show-overflow-tooltip prop="settleAmount" min-width="140px" />
<el-table-column v-if="type !== 'add'" align="center" label="调整金额(元)" show-overflow-tooltip min-width="140px">
<template slot-scope="scope">
{{ scope.row.adjustAmount }}
</template>
</el-table-column>
<el-table-column v-if="type !== 'add'" align="center" label="账单金额(元)" show-overflow-tooltip min-width="140px">
<template slot-scope="scope">
{{ scope.row.billAmount }}
</template>
</el-table-column>
<el-table-column v-if="type === 'audit'" fixed="right" align="center" label="审核说明" show-overflow-tooltip min-width="240px">
<template slot-scope="scope">
<el-input v-model="scope.row.operationExp" v-trim type="textarea" clearable :autosize="{ minRows: 3, maxRows: 5 }" show-word-limit maxlength="500" placeholder="请输入审核说明" />
</template>
</el-table-column>
<el-table-column v-if="type === 'add'" align="center" label="异常原因" prop="errorMsg" show-overflow-tooltip min-width="240px">
<template slot-scope="scope">
<span v-if="type === 'add'" :class="{'red_exceptionId': scope.row.errorMsg}">{{ !scope.row.errorMsg?'无异常':scope.row.errorMsg }}</span>
</template>
</el-table-column>
<el-table-column v-if="type === 'add'" fixed="right" label="操作" align="center" width="100px">
<template slot-scope="scope">
<el-tooltip v-if="checkPermission('billing:waterbilling:Submit')&&type === 'add'" effect="dark" content="删除" placement="top">
<el-button class="handleTxt" type="text" size="small" @click.native.prevent="handDel(scope.row)">
<i class="el-icon-delete" style="color: #69B0FF;font-size: 16px;" />
</el-button>
</el-tooltip>
</template>
</el-table-column>
</el-table>
<!-- 分页按钮 -->
<div v-show="templeList.length>0" class="page_cls">
<div>共 {{ templeList.length }} 条</div>
<el-tooltip effect="dark" content="上一页" placement="top">
<button class="btn_cls" :disabled="currentPage === 1" @click="previousPage"><i class="el-icon-arrow-left" /></button>
</el-tooltip>
<el-tooltip effect="dark" content="下一页" placement="top">
<button class="btn_cls" :disabled="currentPage * pageSize >= templeList.length" @click="nextPage"><i class="el-icon-arrow-right" /></button>
</el-tooltip>
</div>
----------------------css--------------------
.page_cls{
padding-top: 10px;
display: flex;
align-items: center;
justify-content: right;
.btn_cls{
background-color: #F5F6F9;
border: none;
height: 30px;
width: 30px;
border-radius: 3px;
cursor: pointer;
margin: 0 2px;
}
}