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

Detailed explanation of using INS and DEL to mark document changes

ins and del were introduced in HTML 4.0 to help au...

Detailed explanation of MySQL transactions and MySQL logs

Transactional Characteristics 1. Atomicity: After...

Media query combined with rem layout in CSS3 to adapt to mobile screens

CSS3 syntax: (1rem = 100px for a 750px design) @m...

Navicat for MySQL 11 Registration Code\Activation Code Summary

Recommended reading: Navicat12.1 series cracking ...

Solution to Nginx SSL certificate configuration error

1. Introduction When a web project is published o...

How to set MySQL foreign keys for beginners

Table of contents The role of foreign keys mysql ...

Summary of Nginx load balancing methods

To understand load balancing, you must first unde...

The difference between MySQL user management and PostgreSQL user management

1. MySQL User Management [Example 1.1] Log in to ...

Which loop is the fastest in JavaScript?

Knowing which for loop or iterator is right for o...

How to implement page jump in Vue project

Table of contents 1. Create a vue-cli default pro...

HTML Basics_General Tags, Common Tags and Tables

Part 1 HTML <html> -- start tag <head>...

Vue basics MVVM, template syntax and data binding

Table of contents 1. Vue Overview Vue official we...

The difference between z-index: 0 and z-index: auto in CSS

I've been learning about stacking contexts re...

An article to teach you HTML

If you are not committed to becoming an artist, t...