Vue3 element-ui implements Pagination paging component--encapsulation paging

What is Pagination paging component?

In the web development of the B-side, the paging component or pager is one of the more commonly used controls. It usually cooperates with tables or lists to realize the function of disassembling data by paging when the amount of data is large.

1.scrollTo and scroll parallax

The scrollTo method is defined in the HTML DOM, usage: scrollTo(xpos,ypos), scroll the content to the current specified position. But this can only be said to move at best and not to scroll, and there seems to be no sliding effect displayed. Fortunately, JQuery provides enough convenient plug-ins, one of which can provide smooth scrolling

The plug-in is called jquery.scrollTo.js, of course, the premise is that the jquery library is included first. Moreover, it has been well encapsulated in itself, and it only needs to simply call the function on the label to achieve smooth scrolling, which is very easy to use. Like this:

 $(function(){   
     $(".nav_pro").click(function(){   
         $.scrollTo('#pro',500);   
     });   
     $(".nav_news").click(function(){   
         $.scrollTo('#news',800);   
     });   
     $(".nav_ser").click(function(){   
         $.scrollTo('#ser',1000);   
     });   
     $(".nav_con").click(function(){   
         $.scrollTo('#con',1200);   
     });   
     $(".nav_job").click(function(){   
         $.scrollTo('#job',1500);   
     });   
 });  

One of the two parameters of scrollTo defines the element object to be scrolled, and the other is the duration of scrolling, calculated in milliseconds.

Smooth scrolling is only the most basic method that this plugin can implement. You can consider continuing to do other applications on this basis, such as displaying documents, simulating PPT effects, and so on.

2. Use vue3 vue-scrollto

Install vue-scrollto

npm install --save vue-scrollto

Then introduce in main.js

const VueScrollTo = require('vue-scrollto');

app.use(VueScrollTo)

Finally, you can use it on the corresponding page

 <div class="flexca broadside_item" v-scroll-to="'#element'">
          <img src="@/assets/img/icon_41.png" alt="" />
          <img class="msg" src="@/assets/img/icon_42.png" alt="" v-if="false" />
        </div>

v-scroll-to is followed by the position where the click needs to jump to the page element;

'#element' can be named freely, the class name or id name of the element

3. Vue paging component--encapsulation: Method 1 (commonly used)

Why encapsulation?

The paging function is used in many scenarios, so consider encapsulating it as a global component. The cost of
self- encapsulation is low, and you can add any functions you need
. Compared with using ready-made component libraries, the size of self-encapsulating code is controllable

The package in the element component used by the paging component can be used globally, which is convenient and fast

The component of the element component is used, and the element dependency needs to be installed. I won’t say much about how to install it.

1. Create a new scroll-to.js in utils

scroll-to.js content:

Math.easeInOutQuad = function(t, b, c, d) {

    t /= d / 2

    if (t < 1) {

      return c / 2 * t * t + b

    }

    t--

    return -c / 2 * (t * (t - 2) - 1) + b

  }

  // requestAnimationFrame for Smart Animating http://goo.gl/sx5sts

  var requestAnimFrame = (function() {

    return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || function(callback) { window.setTimeout(callback, 1000 / 60) }

  })()

  /**

   * Because it's so fucking difficult to detect the scrolling element, just move them all

   * @param {number} amount

   */

  function move(amount) {

    document.documentElement.scrollTop = amount

    document.body.parentNode.scrollTop = amount

    document.body.scrollTop = amount

  }

  function position() {

    return document.documentElement.scrollTop || document.body.parentNode.scrollTop || document.body.scrollTop

  }

  /**

   * @param {number} to

   * @param {number} duration

   * @param {Function} callback

   */

  export function scrollTo(to, duration, callback) {

    const start = position()

    const change = to - start

    const increment = 20

    let currentTime = 0

    duration = (typeof (duration) === 'undefined') ? 500 : duration

    var animateScroll = function() {

      // increment the time

      currentTime += increment

      // find the value with the quadratic in-out easing function

      var val = Math.easeInOutQuad(currentTime, start, change, duration)

      // move the document.body

      move(val)

      // do the animation unless its over

      if (currentTime < duration) {

        requestAnimFrame(animateScroll)

      } else {

        if (callback && typeof (callback) === 'function') {

          // the animation is done so lets callback

          callback()

        }

      }

    }

    animateScroll()

  }

2. Create a new Pagination in components and create a new index.vue file

index.vue content:

<template>

  <div : class="pagination-container">

    <el-pagination

      :background="background"

      :current-page.sync="currentPage"

      :page-size.sync="pageSize"

      :layout="layout"

      :page-sizes="pageSizes"

      :pager-count="pagerCount"

      :total="total"

      v-bind="$attrs"

      @size-change="handleSizeChange"

      @current-change="handleCurrentChange"

    />

  </div>

</template>

<script>

import { scrollTo } from '../../utils/scroll-to'

export default {

  name: 'Pagination',

  props: {

    total: {

      required: true,

      type: Number

    },

    page: {

      type: Number,

      default: 1

    },

    limit: {

      type: Number,

      default: 20

    },

    pageSizes: {

      type: Array,

      default() {

        return [5,10, 20, 30, 50]

      }

    },

    // 移动端页码按钮的数量端默认值5

    pagerCount: {

      type: Number,

      default: document.body.clientWidth < 992 ? 5 : 7

    },

    layout: {

      type: String,

      default: 'total, sizes, prev, pager, next, jumper'

    },

    background: {

      type: Boolean,

      default: true

    },

    autoScroll: {

      type: Boolean,

      default: true

    },

    hidden: {

      type: Boolean,

      default: false

    }

  },

  data() {

    return {

    };

  },

  computed: {

    currentPage: {

      get() {

        return this.page

      },

      set(val) {

        this.$emit('update:page', val)

      }

    },

    pageSize: {

      get() {

        return this.limit

      },

      set(val) {

        this.$emit('update:limit', val)

      }

    }

  },

  methods: {

    handleSizeChange(val) {

      if (this.currentPage * val > this.total) {

        this.currentPage = 1

      }

      this.$emit('pagination', { page: this.currentPage, limit: val })

      if (this.autoScroll) {

        scrollTo(0, 800)

      }

    },

    handleCurrentChange(val) {

      this.$emit('pagination', { page: val, limit: this.pageSize })

      if (this.autoScroll) {

        scrollTo(0, 800)

      }

    }

  }

}

</script>

<style scoped>

.pagination-container {

  /* background: #fff; */

  /* padding: 32px 16px; */

  height: 50px;

  margin-top:30px;

  /* position: fixed; */

  right: 90px;

  bottom: 20px;

}

.pagination-container.hidden {

  /* display: none; */

}

</style>

3. Introduce the grouping component in main.js and hang it globally

import Pagination from "./components/Pagination";
Vue.component('Pagination', Pagination)

4. The pages that need to be used can be used by using the global method name

 <pagination
            v-show="total > 0"
            :total="total"
            :page.sync="queryParams.pageNum"
            :limit.sync="queryParams.pageSize"
            @pagination="getSocialNumberList"
          />

Copy and paste can be used normally, and the style problem can be adjusted. @pagination is a method to obtain the list, which is touched when the number of items or pages is changed.

4. Vue paging component--encapsulation: Method 2 (understand)

The difference between method 2 and method 1: method 1 is global import, method 2 is partial import of components, that is, import at the place of use;

Another difference is in point 5 of method two , which can also be used in method one.

1. The principle of pagination:

1.1 The principle of paging

Pagination is realized through the built-in component pagination of element-ui. Any pagination consists of the following five parts:

  • total number of records

  • Number of records displayed per page

  • total pages

  • What is the current page

  • All records on the current page

1.2 True and false pagination

Pagination is actually a component. The parameters commonly used in paging are set in the component, so that the pagination component can get the parameter values ​​commonly used in paging, which can realize paging.

True pagination: When you are currently on the home page, when you click "Second Page" or "Next Page", a request will be sent to the backend again to request the data of the second page

False paging: At the beginning, a request is sent from the backend to obtain all the data, and the frontend paginates the data in the form of components, and when the pagination button is clicked, the data is actually already in the cache of the browser cache, and there is no need to request again backend interface

Second, the use of backend-PageHelper:

1. First, add the pageHelper dependency in pom.xml

<!--分页插件-->
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper</artifactId>
            <version>5.1.10</version>
        </dependency>

2. Write the "SQL query" statement in the mapping file; Note: Do not use ";" at the end of the statement

<select id="QueryProductsById" resultMap="ProductsMap">
        SELECT
        <include refid="products_cloumn_list"/>
        FROM products WHERE id = #{Id}
    </select>

3. Write the Controller class. Note: the startPage method of PageHelper must be called before the method in the interface is called.

@RequestMapping("/PageInfo")
    public PageInfo<Products> pageInfo(int pageNum, int pageSize) {
        PageHelper.startPage(pageNum, pageSize);
        List<Products> list = productsDaoService.QueryProducts();
        PageInfo<Products> pageInfo = new PageInfo<Products>(list);
        return pageInfo;
    }

4. Start the tomcat server and use Apipost to test the interface. If there is no problem with the interface, the return value information will be obtained in the "real-time response".

3. The use of front-end-Pagination:

(Before using pagination, you need to have a preliminary understanding of element-UI), because using pagination is a process of "carrying" code from vue-element-admin. For details, you can search for "pagination" on the element integration to view

1. Add the content of the <template> tag to the page that needs to be paginated (the first 1, 2, and 3 steps are the same as method 1)

 <pagination
      :total="total"
      :page.sync="listQuery.page"
      :limit.sync="listQuery.limit"
      @pagination="getList" />

2. According to element integration, import the Pagination component in <script>

import Pagination from '@/components/Pagination'

The content of index.vue in the pagination component is as follows:

<template>
  <div :class="{'hidden':hidden}" class="pagination-container">
    <el-pagination
      :background="background"//背景色  true 为有背景色,false为无背景色
      :current-page.sync="currentPage"   //当前页
      :page-size.sync="pageSize" //页面的大小
      :layout="layout"   
      :page-sizes="pageSizes"
      :total="total" //总页数
      v-bind="$attrs"
      @size-change="handleSizeChange"
      @current-change="handleCurrentChange"
    />
  </div>
</template>

<script>
import { scrollTo } from '@/utils/scroll-to'

export default {
  name: 'Pagination',
  props: {
    total: {
      required: true,
      type: Number
    },
    page: {
      type: Number,
      default: 1
    },
    limit: {
      type: Number,
      default: 20
    },
    pageSizes: {
      type: Array,
      default() {
        return [10, 20, 30, 50]
      }
    },
    layout: {
      type: String,
      default: 'total, sizes, prev, pager, next, jumper'
    },
    background: {
      type: Boolean,
      default: true
    },
    autoScroll: {
      type: Boolean,
      default: true
    },
    hidden: {
      type: Boolean,
      default: false
    }
  },
  computed: {
    currentPage: {
      get() {
        return this.page
      },
      set(val) {
        this.$emit('update:page', val)
      }
    },
    pageSize: {
      get() {
        return this.limit
      },
      set(val) {
        this.$emit('update:limit', val)
      }
    }
  },
  methods: {
    handleSizeChange(val) {
      this.$emit('pagination', { page: this.currentPage, limit: val })
      if (this.autoScroll) {
        scrollTo(0, 800)
      }
    },
    handleCurrentChange(val) {
      this.$emit('pagination', { page: val, limit: this.pageSize })
      if (this.autoScroll) {
        scrollTo(0, 800)
      }
    }
  }
}
</script>

<style scoped>
.pagination-container {
  background: #fff;
  padding: 32px 16px;
}
.pagination-container.hidden {
  display: none;
}
</style>

As with method 1, you can make appropriate modifications, or if you don’t want certain functions, just delete the corresponding part

3. Register the local component, and because when adding the <template> tag, there are attributes and methods bound, so the attribute must be declared and the method should be implemented

export default {
    components: { Pagination },
    data() {
      return {
        list: [{
            //查询出来的商品集合
        }],
        total: 0,
        listQuery: {
          page: 1,
          limit: 20
        }
      }
    },
  methods: {
        getList() {
      // 获取数据
    }
  }
}

4. Implement the getList() method, send axios request to obtain the data passed by the backend, and assign the total number of items returned and the decibel of data information to the local total and list collections respectively

  getList() {
        // 获取数据
        var vm = this;
        this.axios({
          method: 'get',
          url: 'http://localhost:8080/ssm-template/products/PageInfo?pageNum='+vm.listQuery.page+'&pageSize='+vm.listQuery.limit
        })
          .then(function (response) {
            vm.total = response.data.total;
            vm.list = response.data.list;
          })
      },

5. Use the created() method to call the getList() method when the page is loaded to realize pagination:

 created() {
      this.getList()
    },

The renderings are as follows:

5. Implementation ideas: How to implement the pager component

Idea: judge based on consecutive page numbers

  • 需要添加分页器的组件(Search组件)中

           <!-- 分页器 -->
          <Pagination
            :pageNo="searchParams.pageNo"
            :pageSize="searchParams.pageSize"
            :total="total"
            :continues="5"
            @getPageNo="getPageNo"
          />

1)在分页器组件上传递【当前页码pageNo】、【每页展示的数据pageSize】、【总的数据total】、【连续的页码(重要)】,定义一个【自定义事件getPageNo】把用户点击的【当前页码pageNo】传递回来,并进行数据请求

2)methods中定义函数接受分页器传回来的【当前页pageNo】

1)分页器,分成三部分 ------【如下图】

  • 分页器组件(Pagination)中

1)通过props取得 Search组件传递的参数

     props: ["pageNo", "pageSize", "total", "continues"],

2)在分页器组件计算属性computed中计算总共多少页/最后一页 - this.total / this.pageSize

【记得向上取整Math.ceil(),例:当总的数据total=30,每页的数据pageSize=3,那么10页刚刚好展示完毕,如果每页的数据pageSize=4,有7页展示4条数据,还有2条需要下一页展示,所以进行取整,Math.ceil(30/4)=8】

3)在分页器组件计算属性computed中计算连续页码【至少5页】的起始数字start、结束数字end【当前页pageNo在连续页码中】

  • 情况判断一:连续的页码 > 总的页数 【start=1,end=总的页数】

  • 情况判断二:连续的页码 < 总的页数 【计算 start = pageNo - parseInt(continues / 2)、end = pageNo + parseInt(continues / 2);】

  • 分情况一:start数字出现0 | 负数 【continues=5,pageNo=1、2的时候】

  • 分情况二:end数字大于总页码 【continues=5,totalPage=30,pageNo=29、30的时候】

  • 记得:最后把 start、end返回

  • 上下一页 、第一页、最后一页的判断

  • 上一页:如果当前页pageNo=1,就不显示上一页按钮,绑定点击事件,点击触发getPageNo自定义事件,把当前页pageNo-1当参数传递回search组件,请求上一页的数据

  • 第一页:如果连续页码的起始数字start>1,就显示前面定义好的第一页;小于的话,显示连续页码中的第一页按钮。点击事件同上,由于可能处理选中状态,所以绑定一个类【已经在css中定义好的】,添加选中颜色,当然需要判断是否是选中的页

  • 省略...小点:当连续页码的start=3时,显示,也就表示,他们之间还有一页

  • 连续页码:通过v-for遍历数字,遍历连续页码中end,并判断其中的元素page>start,才显示【因为传过来的连续页码为5,所以在分页器中连续页码出现最大的就是end-start=5,去掉start之前的页码,才能使连续页码为5】,其他同上

  • 省略...小点 | 最后一页 | 下一页:计算同上【totalPage是上面已经算完的总页数|最后一页】

  • 静态组件

<template>
  <div class="pagination">
    <button>1</button>
    <button>上一页</button>
    <button>···</button>
 
    <button>3</button>
    <button>4</button>
    <button>5</button>
    <button>6</button>
    <button>7</button>
    
    <button>···</button>
    <button>9</button>
    <button>上一页</button>
    
    <button style="margin-left: 30px">共 60 条</button>
  </div>
</template>
 
<script>
  export default {
    name: "Pagination",
  }
</script>
 
<style lang="less" scoped>
  .pagination {
    button {
      margin: 0 5px;
      background-color: #f4f4f5;
      color: #606266;
      outline: none;
      border-radius: 2px;
      padding: 0 4px;
      vertical-align: top;
      display: inline-block;
      font-size: 13px;
      min-width: 35.5px;
      height: 28px;
      line-height: 28px;
      cursor: pointer;
      box-sizing: border-box;
      text-align: center;
      border: 0;
 
      &[disabled] {
        color: #c0c4cc;
        cursor: not-allowed;
      }
 
      &.active {
        cursor: not-allowed;
        background-color: #409eff;
        color: #fff;
      }
    }
  }
</style>

6.el-pagination实现分页功能

如果只放el-pagination组件,只是一个静态的分页展示,还需要绑定数据列表,达到动态分页功能。

静态展示如下

其中最主要的几行代码如图:

对于currentPage、pageSize都要在数据中定义一下,如图

对于handleSizeChange、handleCurrentChange都要实现一下该函数

接下来是最最关键的一步,需要绑定数据加载

对于需要动态加载的组件,进行绑定,比如说绑定到el-table或者el-card中,我的数据储存在carddata中,.slice就是用来分割数据的,根据当前页面的大小以及页面定位进行数据的展示。

前后端分页:

需要注意的是当我们使用后端分页时,要注意前端就不能进行分页了,前端就只负责请求,后台已经把页分好了,不然你的页面就只会显示第一页的数据,其他页都是显示“暂无数据”;前端分页相对来说不会这么麻烦,但还是要多注意。

后端分页:

就是数据在后台已经分好页了,前端只需要用请求去获取数据即可,后端分页的好处是只会把当前页的数据给拿下来,网页加载的速度会很快,但是不足就是每跳转一次,前端都要向后台发送一次请求。

前端分页:

就是用请求从后台把所有的数据拿下来,然后进行分页,如果当数据足够大时,网页就会加载的很慢,唯一的好处就是只需要向后台请求一次就可以了。

参考链接:

https://blog.csdn.net/weixin_69318049/article/details/127072290

https://blog.csdn.net/weixin_49931650/article/details/127828464?utm_medium=distribute.pc_relevant.none-task-blog-2~default~baidujs_baidulandingword~default-4-127828464-blog-127072290.pc_relevant_3mothn_strategy_recovery&spm=1001.2101.3001.4242.3&utm_relevant_index=7

Guess you like

Origin blog.csdn.net/coinisi_li/article/details/128952886