vue实现滚动加载的表格

2022-04-15 0 715
目录
  • 实现效果
  • 滚动加载知识储备
  • 组件封装
    • 1. 组件命名
    • 2. 提供的props
    • 3.使用举例
  • 组件封装总结
    • 1.尽可能地使用computed计算属性
    • 2.给表格提供插槽
  • 另一种滚动加载数据的实现

    实现效果

    vue实现滚动加载的表格

    码云地址

    滚动加载知识储备

    参考ant-design-vue中list滚动加载的思路,使用vue-infinite-scroll加上vue-virtual-scroller作为解决方案。

    组件封装

    因为整个系统使用的框架是ant-dsign-vue,所以组件封装的变量命名风格尽可能的与a-table保持一致。

    1. 组件命名

    XScrollTable.vue

    2. 提供的props

    必填字段:

    dataSource — 数据源

    columns — 表格展示的列信息,插槽用法和a-table不完全一样,下面会提到。

    itemSize — 每行数据的高度

    选填字段:

    rowKey — 数据主键标识,默认为’key’

    height — 表格展示区域的高度,默认为500

    pageSize — 表格滚动每次滚动加载的数据量,默认为30

    infiniteScrollDistance — 表格触发加载的距离条件,默认为10

    rowSelection — 表格多选配置,已处理的属性有selectedRowKeys、onChange、width。默认为null,不展示多选。

    3.使用举例

    首先初始化10000条数据,放在表格中进行显示。

    let data = new Array(10000).fill(1);
    
    data = data.map((item1, index) => {
        let item = {};
        item.id = index;
        item.age = "姓名";
        item.address = "地址";
        return item;
    });
    export default data;
    

    注意:这里之所以加了fill(1),是因为通过Array构造函数产生的数据全是empty,没有数组索引,无法进行map循环。

    加载表格

    <x-scroll-table
                    style="margin-top: 10px"
                    row-key="id"
                    :itemSize="22"
                    :rowSelection="{selectedRowKeys: selectedRowKeys, onChange: onSelectChange,width:50}"
                    :columns="columns"
                    :dataSource="data">
                <template slot="action" slot-scope="{record,text}">
                    <a @click="handleDetail(record)">详情</a>
                </template>
            </x-scroll-table>
    

    组件封装总结

    1.尽可能地使用computed计算属性

    虽然只是简单地封装了表格,但还是需要定义了很多的属性,使用计算属性代替在data里定义变量,可以减少变量的维护工作量。

    整个组件只定义了一个page变量,其它都是使用计算属性的方式。

      data() {
        return {
          // 当前展示页数
          page: 1,
        };
      },
    

    举个栗子:

    通过page属性定义一个计算属性来表示当前已经加载的数据量

     // 展示的最大下标数量,存在比总数据条数多的情况,使用slice解决这个问题
        lastIndex() {
          return this.pageSize * this.page;
        },
    

    通过这个计算属性同时衍生出其他的计算属性

    // 表示表格数据是否已经加载完毕  
    busy() {
          return this.lastIndex >= this.dataSource.length;
        },
     // 当前已经加载到RecycleScroller滚动组件的数据
        tableData() {
          return this.dataSource.slice(0, this.lastIndex);
        },
    

    通过一个page属性衍生出一系列的计算属性,我只需要维护page属性,其他都是自动计算的。

    2.给表格提供插槽

    首先通过表格传入的columns参数,计算出需要渲染的列,这里同样使用计算属性。

     // 将列数组转为列对象,将columnFieldKey值作为键,数组项作为值
        columnMap() {
          return this.columns.reduce((returnValue, cur) => {
            returnValue[cur[columnFieldKey]] = cur;
            return returnValue;
          }, {});
        },
        // 取数组里的列键值--columnFieldKey
        columnKeys() {
          return this.columns
              .map(item => item[columnFieldKey]);
        },
    

    在template中遍历

    <div v-for="(key) of columnKeys"
                 class="ellipsis-cell"
                 :key="key"
                 :style="itemStyle(columnMap[key])"
            >
              <slot v-if="izSlotRender(columnMap[key])"
                    :name="columnMap[key].scopedSlots.customRender"
                    :record="row"
                    :text="row[key]">
              </slot>
              <span v-else :title="row[key]">{{ renderItem(row, index, key) }}</span>
            </div>
    
      // 是否使用插槽渲染
        izSlotRender(item) {
          return item.scopedSlots && item.scopedSlots.customRender;
        },
    

    如果在定义columns时传入了scopedSlots和customRender,将使用插槽渲染。

    但是这里存在和ant-design-vue中表格插槽渲染不一样的地方。

    我通过slot标签定义的插槽,在父组件获取插槽参数的时候,只能使用slot-scope=”{record,text}”对象解构的方式。而ant-design-vue表格是可以直接使用slot-scope=”record,text”获取参数的。

    另一种滚动加载数据的实现

    table数据多的时候打开页面会加载一会才显示数据,这样体验不好,所以要做滚动加载数据

    <el-table :data="materielList" style="width: 100%" class="familyDataDetail" height="250">
                    <el-table-column prop="eventId" label="事件ID">
                        <template scope="scope">
                            <label>{{eventMap[scope.row.eventId] == null ? '--': eventMap[scope.row.eventId].sn}}</label>
                        </template>
                    </el-table-column>
                    <el-table-column prop="title" label="对应事件">
                        <template scope="scope">
                            <label>{{eventMap[scope.row.eventId] == null ? '--': eventMap[scope.row.eventId].title}}</label>
                        </template>
                    </el-table-column>
                    <el-table-column prop="age" label="负责人">
                        <template scope="scope">
                            <label>{{eventMap == null || eventMap[scope.row.eventId] == null || eventMap[scope.row.eventId].personalInformation == null ? '--':
                                eventMap[scope.row.eventId].personalInformation.name}}</label>
                        </template>
                    </el-table-column>
                    <el-table-column prop="birthday" label="物料名称">
                        <template scope="scope">
                            <label>{{materirlName}}</label>
                        </template>
                    </el-table-column>
                    <el-table-column prop="idcardNo" label="状态">
                        <template scope="scope">
                            <label>{{formatType(scope.row.type)}}</label>
                        </template>
                    </el-table-column>
                    <el-table-column prop="relationship" label="数量">
                        <template scope="scope">
                            <label>{{formatUseNum(scope.row.useNum)}}</label>
                        </template>
                    </el-table-column>
                    <el-table-column prop="ethtic" label="使用时间">
                        <template scope="scope">
                            <label>{{changeTime(scope.row.createOn)}}</label>
                        </template>
                    </el-table-column>
                </el-table>

    下面是js部分 

    methods: {
      init (param) {
      let id = param.param && param.param.id
      if(id){
          this.start = 0
              MaterialRecordService.query({param: {baseId: this.baseId, materialId: id},start: this.start,limit: 30}).then(rsp => {//初次请求数据,30条
                this.start += 30
                this.materielList = rsp.data
                MissionEventService.microList({ids: rsp.data.map(n => n.eventId)}).then(rsp3 => {
                    this.eventMap = {}
                    rsp3.data.forEach(n => (this.eventMap[n.id] = n))
                     
                })   
              })
      }
      },
      onScroll() {
          let inner = document.querySelector('.el-table__body-wrapper');
          if(inner.scrollHeight - inner.scrollTop <= inner.clientHeight){//为true时证明已经到底,可以请求接口
            if(this.flag){//设一个滚动事件的开关,(在data里面声明 flag: true)默认为true
                 this.flag = false             
                 MaterialRecordService.query({param: {baseId: this.baseId, materialId: this.entity.id},start: this.start,limit:30}).then(rsp => {//每次加载30条
                  this.materielList = this.materielList.concat(rsp.data)
                      this.start += 30
                      this.flag = true
                  MissionEventService.microList({ids: rsp.data.map(n => n.eventId)}).then(rsp3 => {
                   rsp3.data.forEach(n => (this.eventMap[n.id] = n))
                  })
                 })            
            }
          }
       }
    },
    mounted () {
          this.init({...this.param})<br>    //监听表格dom对象的滚动事件
          document.querySelector('.el-table__body-wrapper').addEventListener('scroll', this.onScroll);
        }

    在这里我要说明一下监听的dom对象是哪一个

    vue实现滚动加载的表格

    我还要解释下scrollHeight、scrollTop、clientHeight这三个属性

    vue实现滚动加载的表格

    这是我截的别人的图加了几笔

    scrollHeight:网页正文全文高度,

    scrollTop:网页滚动的高度,

    clientHeight:网页可视区域的高度

    以上就是vue实现滚动加载的表格的详细内容,更多关于vue 滚动加载的表格的资料请关注NICE源码其它相关文章!

    免责声明:
    1、本网站所有发布的源码、软件和资料均为收集各大资源网站整理而来;仅限用于学习和研究目的,您必须在下载后的24个小时之内,从您的电脑中彻底删除上述内容。 不得使用于非法商业用途,不得违反国家法律。否则后果自负!

    2、本站信息来自网络,版权争议与本站无关。一切关于该资源商业行为与www.niceym.com无关。
    如果您喜欢该程序,请支持正版源码、软件,购买注册,得到更好的正版服务。
    如有侵犯你版权的,请邮件与我们联系处理(邮箱:skknet@qq.com),本站将立即改正。

    NICE源码网 JavaScript vue实现滚动加载的表格 https://www.niceym.com/28112.html