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

An article to deal with Mysql date and time functions

Table of contents Preface 1. Get the current time...

VMware virtualization kvm installation and deployment tutorial summary

Virtualization 1. Environment Centos7.3 Disable s...

Nginx solves cross-domain issues and embeds third-party pages

Table of contents Preface difficulty Cross-domain...

A brief analysis of the difference between FIND_IN_SET() and IN in MySQL

I used the Mysql FIND_IN_SET function in a projec...

Should nullable fields in MySQL be set to NULL or NOT NULL?

People who often use MySQL may encounter the foll...

Detailed explanation of the mysql database LIKE operator in python

The LIKE operator is used in the WHERE clause to ...

Install Percona Server+MySQL on CentOS 7

1. Environmental Description (1) CentOS-7-x86_64,...

Tutorial on using hyperlink tags in XHTML

Hyperlink, also called "link". Hyperlin...

How to use Samba to build a shared file service on a Linux server

Recently, our small team needs to share a shared ...

Centos8 (minimum installation) tutorial on how to install Python3.8+pip

After minimizing the installation of Python8, I i...

Application and implementation of data cache mechanism for small programs

Mini Program Data Cache Related Knowledge Data ca...

HTML head tag detailed introduction

There are many tags and elements in the HTML head ...

Docker Nginx container production and deployment implementation method

Quick Start 1. Find the nginx image on Docker Hub...

Vue implements a small weather forecast application

This is a website I imitated when I was self-stud...