后端返一千条数据 把所有数据分成若干组,用定时器分批次渲染,并将分批渲染的数据进行合并表格,自定义分页的前进和后退功能

文章讲述了在处理大量数据时,如何在Vue2应用中使用后端分批返回数据,前端通过定时器实现分批次渲染,以防止页面卡顿,同时介绍了自定义分页功能和表格合并的处理策略。
摘要由CSDN通过智能技术生成
  1. 后端返回数据:后端返回一千条数据给前端。你可以在后端将这些数据分成若干组,每组包含一定数量的数据。

  2. 前端定时器渲染数据:前端使用定时器来逐批次渲染数据,以避免一次性渲染大量数据导致页面卡顿。

 下面是一个简单的示例代码,演示了如何在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>共&nbsp;&nbsp;{{ templeList.length }}&nbsp;&nbsp;条</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;
  }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值