您的位置:

Vue分页详解

一、Vue分页参数

Vue分页中,我们需要了解分页相关的参数,以便配置分页组件。常用的分页参数包括:

  1. 当前页数:用于标识当前显示的页码,可以通过v-model绑定到当前页数的变量上。
  2. 总记录数:用于计算总页数,参与分页算法。可以从后端接口获取。
  3. 每页显示数:用于控制每页显示的记录数,也叫分页大小。
  4. 页码范围:用于控制分页器上显示的页码数量,通常显示3~5个页码。

代码示例:

<template>
  <div class="pagination">
    <span>总共 {{ total }} 条记录</span>
    <ul>
      <li v-if="currentPage>1"><a href="#" @click.prevent="currentPage--"><</a></li>
      <li v-for="page in pages"><a href="#" @click.prevent="currentPage=page">{{ page }}</a></li>
      <li v-if="currentPage<totalPage"><a href="#" @click.prevent="currentPage++">></a></li>
    </ul>
  </div>
</template>

<script>
export default {
  name: "Pagination",
  props: {
    total: Number,
    pageSize: {
      type: Number,
      default: 10
    },
    range: {
      type: Number,
      default: 3
    },
    currentPage: {
      type: Number,
      default: 1
    },
  },
  computed: {
    totalPage () {
      return Math.ceil(this.total / this.pageSize)
    },
    pages () {
      let from = Math.max(1, this.currentPage - this.range)
      let to = Math.min(this.totalPage, this.currentPage + this.range)
      let pages = []
      for (let i = from; i <= to; i++) {
        pages.push(i)
      }
      return pages
    },
  },
}
</script>

二、Vue分页面

Vue分页面是指根据后端接口返回的数据进行前端分页处理展示。

示例页面中,我们需要获取分页参数后,通过计算得到展示的分页列表,再将每页显示数和当前页码作为参数传递给后端接口获取分页数据。分页数据获取后,需要用v-for指令进行循环展示。

代码示例:

<template>
  <div class="pagination">
    <ul>
      <li v-for="item in pagedData" :key="item.id">{{ item.title }}</li>
    </ul>
    <pagination
      :total="total"
      :pageSize="pageSize"
      @update:currentPage="loadPageData"
    />
  </div>
</template>

<script>
import Pagination from "@/components/Pagination";
export default {
  components: { Pagination },
  data () {
    return {
      currentPage: 1,
      pageSize: 10,
      total: 100,
      data: []
    }
  },
  created () {
    this.loadData()
  },
  methods: {
    async loadData () {
      // 模拟后端返回数据
      let res = await fetch(`api/data?page=${this.currentPage}&size=${this.pageSize}`)
      let { data, total } = await res.json()
      this.data = data
      this.total = total
    },
    loadPageData (currentPage) {
      this.currentPage = currentPage
      this.loadData()
    }
  },
  computed: {
    pagedData () {
      let start = (this.currentPage - 1) * this.pageSize
      let end = start + this.pageSize
      return this.data.slice(start, end)
    }
  }
}
</script>

三、Vue分页组件

为了方便重复使用,在Vue中可以封装成一个组件进行调用。常用的分页组件包括:element-ui的Pagination、bootstrap-vue的b-pagination、vue-pagination等,这里以element-ui为例介绍。

element-ui的Pagination组件需要注意的是,它的currentPage属性要使用v-model绑定。此外,该组件还提供了一个layout属性,用于自定义分页器布局,可以通过字符串数组来指定布局元素的位置。

代码示例:

<template>
  <div>
    <el-pagination
      layout="total,sizes,prev,pager,next,jumper"
      :page-sizes="[10, 20, 50, 100]"
      :total="total"
      :page-size="pageSize"
      v-model="currentPage"
      @current-change="loadData"
    />
    <ul>
      <li v-for="item in data" :key="item.id">{{ item.title }}</li>
    </ul>
  </div>
</template>

<script>
import { Pagination } from "element-ui";
export default {
  components: {
    [Pagination.name]: Pagination
  },
  data () {
    return {
      currentPage: 1,
      pageSize: 10,
      total: 100,
      data: []
    }
  },
  mounted () {
    this.loadData()
  },
  methods: {
    async loadData () {
      // 模拟后端返回数据
      let res = await fetch(`api/data?page=${this.currentPage}&size=${this.pageSize}`)
      let { data, total } = await res.json()
      this.data = data
      this.total = total
    }
  }
}
</script>

四、Vue分页展示图片

在Vue分页过程中,我们可能需要在分页中展示图片,可以使用v-bind绑定src属性,或使用Vue的require方法引入图片资源。

代码示例:

<template>
  <ul>
    <li v-for="item in data" :key="item.id">
      <img :src="item.imageUrl">
      {{ item.title }}
    </li>
  </ul>
</template>

<script>
export default {
  data () {
    return {
      data: [
        { id: 1, title: 'title1', imageUrl: require('@/assets/img1.jpg') },
        { id: 2, title: 'title2', imageUrl: require('@/assets/img2.jpg') },
        { id: 3, title: 'title3', imageUrl: require('@/assets/img3.jpg') },
        ...
      ]
    }
  }
}
</script>

五、Vue分页查询

在Vue分页中,我们可以添加数据查询功能,让用户根据关键字等条件进行数据检索。对于数据查询,通常需要向后台服务器发送请求,并传递查询参数。查询分页逻辑需要在后端服务器进行处理,这里只展示前端的代码。

代码示例:

<template>
  <div>
    <input v-model.trim="keyword" placeholder="请输入关键字">
    <button @click="searchData">搜索</button>

    <el-pagination ... />
    <ul>
      <li v-for="item in data" :key="item.id">{{ item.title }}</li>
    </ul>
  </div>
</template>

<script>
import { Pagination } from "element-ui";
export default {
  components: {
    [Pagination.name]: Pagination
  },
  data () {
    return {
      keyword: "",
      currentPage: 1,
      pageSize: 10,
      total: 0,
      data: []
    }
  },
  methods: {
    async searchData () {
      // 模拟后端返回数据
      let res = await fetch(`api/data?page=${this.currentPage}&size=${this.pageSize}&keyword=${this.keyword}`)
      let { data, total } = await res.json()
      this.data = data
      this.total = total
    },
    async loadData () {
      // 模拟后端返回数据
      let res = await fetch(`api/data?page=${this.currentPage}&size=${this.pageSize}`)
      let { data, total } = await res.json()
      this.data = data
      this.total = total
    }
  }
}
</script>

六、Vue分页原理

Vue分页的原理是通过前端计算获得分页数据,这个过程通过计算分页参数得出分页器上显示的页码列表,然后根据当前页码、每页显示数、数据总记录数等参数计算出当前页码的数据索引,再根据索引获取相关的分页数据。

代码示例:

<template>
  <div>
    <ul>
      <li v-for="item in pagedData">{{ item.title }}</li>
    </ul>
    <div v-if="totalPage">
      <button @click="setCurrentPage(1)" :disabled="currentPage === 1">首页</button>
      <button @click="setCurrentPage(currentPage-1)" :disabled="currentPage === 1">上一页</button>
      <button
        v-for="page in pages"
        :key="page"
        @click="setCurrentPage(page)"
        :class="{ 'active': page === currentPage }"
      >{{ page }}</button>
      <button @click="setCurrentPage(currentPage+1)" :disabled="currentPage === totalPage">下一页</button>
      <button @click="setCurrentPage(totalPage)" :disabled="currentPage === totalPage">尾页</button>
    </div>
  </div>
</template>

<script>
export default {
  data () {
    return {
      currentPage: 1,
      pageSize: 10,
      total: 100,
      data: []
    }
  },
  computed: {
    totalPage () {
      return Math.ceil(this.total / this.pageSize)
    },
    pages () {
      let from = Math.max(1, this.currentPage - 2)
      let to = Math.min(this.totalPage, this.currentPage + 2)
      let pages = []
      for (let i = from; i <= to; i++) {
        pages.push(i)
      }
      return pages
    },
    pagedData () {
      let start = (this.currentPage - 1) * this.pageSize
      let end = start + this.pageSize
      return this.data.slice(start, end)
    }
  },
  methods: {
    setCurrentPage (page) {
      if (page < 1 || page > this.totalPage) {
        return
      }
      this.currentPage = page
      this.loadData()
    },
    async loadData () {
      // 模拟后端返回数据
      let res = await fetch(`data?page=${this.currentPage}&size=${this.pageSize}`)
      let { data, total } = await res.json()
      this.data = data
      this.total = total
    }
  },
  mounted () {
    this.loadData()
  }
}
</script>

七、Vue分页函数

分页函数是一段封装好的可以在Vue分页中重复使用的代码。

代码示例:

<template>
  <div>
    <ul>
      <li v-for="item in pagedData">{{ item.title }}</li>
    </ul>
    <div v-if="totalPage">
      <button @click="setCurrentPage(1)" :disabled="currentPage === 1">首页</button>
      <button @click="setCurrentPage(currentPage-1)" :disabled="currentPage === 1">上一页</button>
      <button
        v-for="page in pages"
        :key="page"
        @click="setCurrentPage(page)"
        :class="{ 'active': page === currentPage }"
      >{{ page }}</button>
      <button @click="setCurrentPage(currentPage+1)" :disabled="currentPage === totalPage">下一页</button>
      <button @click="setCurrentPage(totalPage)" :disabled="currentPage === totalPage">尾页<