Vue implements scroll loading table

Vue implements scroll loading table

Achieve results

Code Cloud Address

Rolling load knowledge reserve

Refer to the idea of ​​list scrolling loading in ant-design-vue, and use vue-infinite-scroll plus vue-virtual-scroller as a solution.

Component packaging

Because the framework used by the entire system is ant-dsign-vue, the variable naming style of component encapsulation is as consistent as possible with a-table.

1. Component Naming

XScrollTable.vue

2. Props provided

Required fields:

dataSource -- data source

Columns -- The column information displayed in the table. The slot usage is not exactly the same as a-table, which will be mentioned below.

itemSize -- the height of each row of data

Optional fields:

rowKey -- data primary key identifier, default is 'key'

Height -- The height of the table display area, the default is 500

pageSize -- The amount of data loaded each time the table scrolls, the default is 30

infiniteScrollDistance -- The distance condition for triggering loading of the table, the default value is 10

rowSelection -- table multi-select configuration, the processed attributes are selectedRowKeys, onChange, width. The default is null, and multiple selections are not displayed.

3. Usage examples

First, initialize 10,000 pieces of data and display them in a table.

let data = new Array(10000).fill(1);

data = data.map((item1, index) => {
    let item = {};
    item.id = index;
    item.age = "name";
    item.address = "address";
    return item;
});
export default data;

Note: fill(1) is added here because the data generated by the Array constructor is all empty, there is no array index, and the map loop cannot be performed.

Loading the table

<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)">Details</a>
            </template>
        </x-scroll-table>

Component packaging summary

1. Use computed properties whenever possible

Although the table is simply encapsulated, many attributes still need to be defined. Using calculated attributes instead of defining variables in data can reduce the workload of variable maintenance.

The entire component only defines one page variable, and the others use calculated properties.

  data() {
    return {
      // Current display page number page: 1,
    };
  },

For example:

Define a calculated property through the page attribute to indicate the amount of data currently loaded

 // The maximum number of subscripts to be displayed may be greater than the total number of data items. Use slice to solve this problem. lastIndex() {
      return this.pageSize * this.page;
    },

Through this calculated property, other calculated properties are derived at the same time

// Indicates whether the table data has been loaded busy() {
      return this.lastIndex >= this.dataSource.length;
    },
 // The data currently loaded into the RecycleScroller scrolling component tableData() {
      return this.dataSource.slice(0, this.lastIndex);
    },

A series of calculated properties are derived from a page property. I only need to maintain the page property, and the others are automatically calculated.

2. Provide slots for the table

First, the columns that need to be rendered are calculated through the columns parameter passed in by the table. The calculated properties are also used here.

 // Convert the column array to a column object, using the columnFieldKey value as the key and the array item as the value columnMap() {
      return this.columns.reduce((returnValue, cur) => {
        returnValue[cur[columnFieldKey]] = cur;
        return returnValue;
      }, {});
    },
    // Get the column key value in the array--columnFieldKey
    columnKeys() {
      return this.columns
          .map(item => item[columnFieldKey]);
    },

Traversing in 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>

  // Whether to use slot rendering izSlotRender(item) {
      return item.scopedSlots && item.scopedSlots.customRender;
    },

If scopedSlots and customRender are passed in when defining columns, slot rendering will be used.

But there is a difference here from the table slot rendering in ant-design-vue.

I defined the slot through the slot tag. When the parent component obtains the slot parameters, I can only use the slot-scope="{record,text}" object deconstruction method. The ant-design-vue table can directly use slot-scope="record,text" to obtain parameters.

Another implementation of scrolling loading data

When there is a lot of table data, it will take a while to load the page before the data is displayed. This is not a good experience, so you need to scroll to load the data.

<el-table :data="materielList" style="width: 100%" class="familyDataDetail" height="250">
                <el-table-column prop="eventId" label="Event 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="Corresponding event">
                    <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="Person in charge">
                    <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="Material name">
                    <template scope="scope">
                        <label>{{materirlName}}</label>
                    </template>
                </el-table-column>
                <el-table-column prop="idcardNo" label="status">
                    <template scope="scope">
                        <label>{{formatType(scope.row.type)}}</label>
                    </template>
                </el-table-column>
                <el-table-column prop="relationship" label="quantity">
                    <template scope="scope">
                        <label>{{formatUseNum(scope.row.useNum)}}</label>
                    </template>
                </el-table-column>
                <el-table-column prop="ethtic" label="Usage time">
                    <template scope="scope">
                        <label>{{changeTime(scope.row.createOn)}}</label>
                    </template>
                </el-table-column>
            </el-table>

Below is the js part

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 => {//First request data, 30 records 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){//When true, it proves that it has reached the bottom and can request the interface if(this.flag){//Set a switch for the scroll event (declare flag: true in data) The default is true
             this.flag = false
                          MaterialRecordService.query({param: {baseId: this.baseId, materialId: this.entity.id},start: this.start,limit:30}).then(rsp => {//Load 30 items at a time 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> //Listen to the scroll event of the table dom object document.querySelector('.el-table__body-wrapper').addEventListener('scroll', this.onScroll);
    }

Here I want to explain which DOM object is being monitored

I also need to explain the three properties of scrollHeight, scrollTop, and clientHeight

This is a screenshot of someone else's picture with some additions

scrollHeight: The height of the full text of the web page.

scrollTop: The height of the web page scrolling,

clientHeight: The height of the visible area of ​​the web page

The above is the detailed content of Vue's implementation of scrolling loading tables. For more information about Vue's scrolling loading tables, please pay attention to other related articles on 123WORDPRESS.COM!

You may also be interested in:
  • Vue implements pure front-end table scrolling and paging loading
  • Vue custom instructions generate uuid scroll monitoring code to achieve the tab table ceiling effect
  • Vue elementUI table table data scroll lazy loading implementation method
  • Vue element-ui table table scroll loading method
  • Vue uses animation to achieve scrolling table effect

<<:  MySQL 5.6 zip package installation tutorial detailed

>>:  Nginx monitoring issues under Linux

Recommend

Summary of Mysql exists usage

Introduction EXISTS is used to check whether a su...

VMware vsphere 6.5 installation tutorial (picture and text)

vmware vsphere 6.5 is the classic version of vsph...

Web design reference firefox default style

Although W3C has established some standards for HT...

Vue template configuration and webstorm code format specification settings

Table of contents 1. Compiler code format specifi...

Users need to know why

When I was in the securities company, because the ...

CSS3 realizes the effect of triangle continuous enlargement

1. CSS3 triangle continues to zoom in special eff...

Design Story: The Security Guard Who Can't Remember License Plates

<br />In order to manage the vehicles enteri...

An article to give you a deep understanding of Mysql triggers

Table of contents 1. When inserting or modifying ...

MySQL kill command usage guide

KILL [CONNECTION | QUERY] processlist_id In MySQL...

Solution to the inaccessibility of Tencent Cloud Server Tomcat port

I recently configured a server using Tencent Clou...

Implementation code for operating mysql database in golang

Preface Golang provides the database/sql package ...

Detailed explanation of webpack-dev-server core concepts and cases

webpack-dev-server core concepts Webpack's Co...

A simple LED digital clock implementation method in CSS3

This should be something that many people have do...

Use of MySQL stress testing tool Mysqlslap

1. MySQL's own stress testing tool Mysqlslap ...