草庐IT

前端实现分页效果

vernin 2023-04-04 原文

前言

        在实际开发中,大部分分页都是配合后端完成的。但是,有时候并不是这样,并非不是这样。后端会一次性返回所有的数据,而我们前端不可能展示所有数据,而是弄一个分页效果。还有一些场景也是需要前端自己弄的分页,如:上传一个Excel表格展示到要页面,当表格的数据足够多,我们也需要弄一个分页效果。

        现在,我就带大家用数组中的slice方法在Vue中实现前端分页效果。

原理

        实现前端分页并不难,用需要用到数组的一个方法slice,看看官网对这个方法的介绍:slice() 方法返回一个新的数组对象,这一对象是一个由 begin 和 end 决定的原数组的浅拷贝(包括 begin,不包括end)。原始数组不会被改变。看完这句话,我们知道该方法在不破坏原数组的情况下返回一个新的数组。其实就对数据切割,并返回被切割的片段。

        slice方法最多可接收两个参数,可传一个或者不传。通过下面栗子来认识这个方法的使用。

使用1:不传递参数

        很明显,当我们不传参数的时候,它会返回整个数组给我们。也就是说,不传参数的时候,他不会对原数组进行切割。

// 准备一个数组
const sect = ['少林派', '武当派', '逍遥派', '峨眉派', '华山派', '日月神教', '古墓派', '全真教', '丐帮', '明教']

// slice 不传参数

const newSect = sect.slice()

console.log(newSect)
// (10) ['少林派', '武当派', '逍遥派', '峨眉派', '华山派', '日月神教', '古墓派', '全真教', '丐帮', '明教']

使用2:传递一个参数

        很明显,当我们传一个参数的时候,它会切割后的数组给我们:

  • 当我们传1的时候,它会从索引为1的元素开始截取直到最后一个元素。

  • 当我们传6的时候,它会从索引为6的元素开始截取直到最后一个元素。

  • 当我们传10的时候,它会从索引为10的元素开始截取取直到最后一个元素。因为这个数组的长度为10,所以他的最大索引为9。所以当第一个参数比数组索引大,就会返回空的数组,这也是情理之中。

  • 当我们传-2的时候,它会从索引为8的元素来说截取,为什么从8开始? 当参数为负数的时候,给大家一个公式:arr.length + 参数,在这个例子就是:10 + (-2) = 8。你也可以说他是反过来数的,也没毛病!(理解最大)

也就是说,传递一个参数时,它会截取从索引为第一个参数到最后一个元素,并返回给我们。当参数比最大索引还大时,会返回空数组;当参数为负数是,它会反着数起始截取位置(不理解的可以使用上面的公式)。

// 准备一个数组
const sect = ['少林派', '武当派', '逍遥派', '峨眉派', '华山派', '日月神教', '古墓派', '全真教', '丐帮', '明教']

const newSect1 = sect.slice(1)
const newSect2 = sect.slice(6)
const newSect3 = sect.sect(10)
const newSect4 = sect.slice(-2)

console.log(newSect1)
// (9) ['武当派', '逍遥派', '峨眉派', '华山派', '日月神教', '古墓派', '全真教', '丐帮', '明教']

console.log(newSect2)
// (4) ['古墓派', '全真教', '丐帮', '明教']

console.log(newSect3)
// []

console.log(newSect4)
// (2) ['丐帮', '明教']

使用3:传递两个参数

        很明显,当我们传两个参数的时候,它也会切割后的数组给我们,但是截取不一定到最后一个元素:

  • 当我们传0和2的时候,它会从索引为0开始截取直到索引为2的元素(不包括索引为2的元素)。

  • 当我们传8和20的时候,它会从索引为8开始截取直到索引为20的元素(不包括索引为2的元素)。因为这个sect数组的的最大索引为9,他只会截取索引为8和9的元素。也可以怎么说:当第二个参数比数组的最大索引还大,就会截取到最后一个元素。

  • 当我们传-2和-1的时候,它会从索引为8开始截取直到索引为9的元素(不包括索引为9的元素)。又是为什么呢? 这里我们也可以使用上面的公式:arr.length + 参数,在这个例子就是,第一个参数:10 + (-2) = 8,第二个参数:10 + (-1) = 9,所以就是 sect.slcie(8, 9)

  • 当我们传-2和-3的时候,原理上它会从索引为8开始截取直到索引为7的元素(不包括索引为7的元素)。这个情况比较特殊,它会返回一个空数组,因为截取是从左往右而不是从右往左

也就是说,传递两个参数时,它会截取从索引为第一个参数开始到索引为第二个参数(不包含这个索引)结束,并返回给我们。当第二个参数比最大索引还大时,会截取到最后一个元素;当第二个参数比第一个参数小时,会返回空数组;当参数为负数是,它会反着数起始截取位置(不理解的可以使用上面的公式)。

// 还是准备一个数组
const sect = ['少林派', '武当派', '逍遥派', '峨眉派', '华山派', '日月神教', '古墓派', '全真教', '丐帮', '明教']

const newSect1 = sect.slice(0, 2)
const newSect2 = sect.slice(8, 20)
const newSect3 = sect.slice(-2, -1)
const newSect4 = sect.slice(-2, -3)

console.log(newSect1)
// (2) ['少林派', '武当派']

console.log(newSect2)
// (2) ['丐帮', '明教']

console.log(newSect3)
// (1) ['丐帮']

console.log(newSect4)
// []

如果你对这个方法很熟,你可以跳过上面的内容,直接阅读下面的内容。如果你都很熟,我相信大佬一定会不吝赐教的!!!

实现

思路:在vue的生命周期函数中,请求全部数据,存到一个数组中。然后封装一个截取数组的方法对存全部数据的数组进行截取,每次调用都返回你想要的数组片段,以实现分页效果。这里使用element-ui+vue演练:

        在data中定义一个接受总数据的变量、一个真正展示的数据的变量(也就是,存放在总数据的数组中截取出来的片段)、一个总页数的变量(也就是,总数据的长度)、一个当前页的变量(默认是第一页)、一个没有大小的变量(默认为每页10条数据)。

        在vue的生命周期函数中,获取全部数据并存到放总数据的变量:tableData中,然后调用queryByPage方法对总数据进行截取,默认截取10条数据(索引为0 - 9),将截取后的数据保存到真正展示数据的变量pageData中。这里一上来就展示10条数据了,当我们改变当前页或者每页大小时,修改变量currentPage或者pageSize,然后执行queryByPage就可以截取我们想要的片段了。

具体queryByPage方法是怎么实现的:

  • 当展示第1页并每页10条数据时:应当截取索引0-9的数据,即tableData.slice(0, 10) => currentPage = 1;pageSize = 10
  • 当展示第1页并每页20条数据时:应当截取索引0-19的数据,即tableData.slice(0, 20) => currentPage = 1;pageSize = 20
  • 当展示第2页并每页10条数据时:应当截取索引10-19的数据,即tableData.slice(10, 20) => currentPage = 2;pageSize = 20

此时可以推出一个公式:tableData.slice((currentPage - 1) x pageSize, currentPage x pageSize)

Vue2版

<template>
  <el-card class="box-card">
    <div slot="header" class="clearfix">
      <span>vue2实现前端分页</span>
    </div>
    <el-table
        :data="pageData"
        border
        size="mini"
        style="width: 100%">
        <el-table-column prop="name" label="姓名" width="120" align="center" />
        <el-table-column prop="age" label="年龄" width="80" align="center" />
        <el-table-column prop="describe" label="描述" align="center" />
      </el-table>

      <el-pagination
        style="margin-top: 12px;text-align: right;"
        @size-change="handleSizeChange"
        @current-change="handleCurrentChange"
        :current-page="currentPage"
        :page-sizes="[10, 20, 50, 100]"
        :page-size="pageSize"
        layout="total, sizes, prev, pager, next, jumper"
        :total="pageTotal">
      </el-pagination>
  </el-card>
</template>

<script>
import axios from 'axios'
export default {
  data () {
    return {
      // 总的数据
      tableData: [],
      // 分页的数据
      pageData: [],
      // 总数据量 默认为 0
      pageTotal: 0,
      // 当前页 默认是第一页
      currentPage: 1,
      // 每页大小 默认每页10条数据
      pageSize: 10
    }
  },
  created () {
    this.fetchData()
  },
  methods: {
    // 改变每页大小的回调
    handleSizeChange (val) {
      this.pageSize = val

      this.pageData = this.queryByPage()
    },
    // 改变当前页的回调
    handleCurrentChange (val) {
      this.currentPage = val

      this.pageData = this.queryByPage()
    },
    // 获取全部数据
    async fetchData () {
      // pubic/table_data.json :默认请求后端数据
      const { data } = await axios.get('/table_data.json')

      this.tableData = data.data
      this.pageTotal = data.data.length

      this.pageData = this.queryByPage()
    },
    // 实现分页的方法
    queryByPage () {
      // 起始位置 = (当前页 - 1) x 每页的大小
      const start = (this.currentPage - 1) * this.pageSize
      // 结束位置 = 当前页 x 每页的大小
      const end = this.currentPage * this.pageSize

      return this.tableData.slice(start, end)
    }
  }
}
</script>

Vue3版

<script setup lang="ts">
	import axios from "axios"
	import { reactive, onMounted } from "vue"

	// 表格数据接口
	interface ITable {
		name: string;
		age: number;
		describe: string;
	}

	let data = reactive({
		tableData: [] as ITable[],  // 总的数据
		pageData: [] as ITable[],   // 分页的数据
		currentPage: 1, // 当前页 默认是第一页
		pageSize: 10,   // 每页大小 默认每页10条数据
		pageTotal: 0 		// 总数据量 默认为 0
	})

	// 在声明周期函数获取数据
	onMounted(() => {
		fetchData()
	})

	const fetchData = async () => {
		// pubic/table_data.json :默认请求后端数据
		const result = await axios.get("/table_data.json")

		data.tableData = result.data.data
		data.pageTotal = result.data.data.length

		data.pageData = queryByPage()
	}

	// 实现分页的方法
	const queryByPage = (): ITable[] => {
		// 起始位置 = (当前页 - 1) x 每页的大小
		let start = (data.currentPage - 1) * data.pageSize
		// 结束位置 = 当前页 x 每页的大小
		let end = data.currentPage * data.pageSize

		// 返回切割数组后的数据
		return data.tableData.slice(start, end)
	}

	// 改变每页大小的方法
	const handleSizeChange = (val: number) => {
		data.pageSize = val
		
		data.pageData = queryByPage()
	}

	// 改变当前页的方法
	const handleCurrentChange = (val: number) => {
		data.currentPage = val
		
		data.pageData = queryByPage()
	}
</script>

<template>
	<el-card class="box-card" style="width: 70%;">
    <template #header>
      <div class="card-header">
        <span>vue3实现前端分页</span>
      </div>
    </template>
		<el-table :data="data.pageData" border style="width: 100%;">
    <el-table-column prop="name" label="姓名" width="150" align="center" />
    <el-table-column prop="age" label="年龄" width="80" align="center" />
    <el-table-column prop="describe" label="描述" align="center" />
  </el-table>
	<el-pagination
		v-model:currentPage="data.currentPage"
		v-model:page-size="data.pageSize"
		:page-sizes="[10, 20, 50, 100]"
		:background="true"
		layout="total, sizes, prev, pager, next, jumper"
		:total="data.pageTotal"
		@size-change="handleSizeChange"
		@current-change="handleCurrentChange"
		style="margin-top: 12px;display: flex;justify-content: flex-end;"
	/>
  </el-card>
</template>

|

有关前端实现分页效果的更多相关文章

  1. ruby - 如何根据特征实现 FactoryGirl 的条件行为 - 2

    我有一个用户工厂。我希望默认情况下确认用户。但是鉴于unconfirmed特征,我不希望它们被确认。虽然我有一个基于实现细节而不是抽象的工作实现,但我想知道如何正确地做到这一点。factory:userdoafter(:create)do|user,evaluator|#unwantedimplementationdetailshereunlessFactoryGirl.factories[:user].defined_traits.map(&:name).include?(:unconfirmed)user.confirm!endendtrait:unconfirmeddoenden

  2. 华为OD机试用Python实现 -【明明的随机数】 2023Q1A - 2

    华为OD机试题本篇题目:明明的随机数题目输入描述输出描述:示例1输入输出说明代码编写思路最近更新的博客华为od2023|什么是华为od,od薪资待遇,od机试题清单华为OD机试真题大全,用Python解华为机试题|机试宝典【华为OD机试】全流程解析+经验分享,题型分享,防作弊指南华为o

  3. 基于C#实现简易绘图工具【100010177】 - 2

    C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.

  4. MIMO-OFDM无线通信技术及MATLAB实现(1)无线信道:传播和衰落 - 2

     MIMO技术的优缺点优点通过下面三个增益来总体概括:阵列增益。阵列增益是指由于接收机通过对接收信号的相干合并而活得的平均SNR的提高。在发射机不知道信道信息的情况下,MIMO系统可以获得的阵列增益与接收天线数成正比复用增益。在采用空间复用方案的MIMO系统中,可以获得复用增益,即信道容量成倍增加。信道容量的增加与min(Nt,Nr)成正比分集增益。在采用空间分集方案的MIMO系统中,可以获得分集增益,即可靠性性能的改善。分集增益用独立衰落支路数来描述,即分集指数。在使用了空时编码的MIMO系统中,由于接收天线或发射天线之间的间距较远,可认为它们各自的大尺度衰落是相互独立的,因此分布式MIMO

  5. 【Java入门】使用Java实现文件夹的遍历 - 2

    遍历文件夹我们通常是使用递归进行操作,这种方式比较简单,也比较容易理解。本文为大家介绍另一种不使用递归的方式,由于没有使用递归,只用到了循环和集合,所以效率更高一些!一、使用递归遍历文件夹整体思路1、使用File封装初始目录,2、打印这个目录3、获取这个目录下所有的子文件和子目录的数组。4、遍历这个数组,取出每个File对象4-1、如果File是否是一个文件,打印4-2、否则就是一个目录,递归调用代码实现publicclassSearchFile{publicstaticvoidmain(String[]args){//初始目录Filedir=newFile("d:/Dev");Datebeg

  6. ruby - Arrays Sets 和 SortedSets 在 Ruby 中是如何实现的 - 2

    通常,数组被实现为内存块,集合被实现为HashMap,有序集合被实现为跳跃列表。在Ruby中也是如此吗?我正在尝试从性能和内存占用方面评估Ruby中不同容器的使用情况 最佳答案 数组是Ruby核心库的一部分。每个Ruby实现都有自己的数组实现。Ruby语言规范只规定了Ruby数组的行为,并没有规定任何特定的实现策略。它甚至没有指定任何会强制或至少建议特定实现策略的性能约束。然而,大多数Rubyist对数组的性能特征有一些期望,这会迫使不符合它们的实现变得默默无闻,因为实际上没有人会使用它:插入、前置或追加以及删除元素的最坏情况步骤复

  7. ruby - "public/protected/private"方法是如何实现的,我该如何模拟它? - 2

    在ruby中,你可以这样做:classThingpublicdeff1puts"f1"endprivatedeff2puts"f2"endpublicdeff3puts"f3"endprivatedeff4puts"f4"endend现在f1和f3是公共(public)的,f2和f4是私有(private)的。内部发生了什么,允许您调用一个类方法,然后更改方法定义?我怎样才能实现相同的功能(表面上是创建我自己的java之类的注释)例如...classThingfundeff1puts"hey"endnotfundeff2puts"hey"endendfun和notfun将更改以下函数定

  8. ruby - 每个页面上的 Jekyll 分页 - 2

    据我们所知,Jekyll默认分页仅支持index.html,我想创建blog.html并在那里包含分页。有什么解决办法吗? 最佳答案 如果您创建一个名为/blog的目录并在其中放置一个index.html文件,那么您可以向_config.yml表示paginate_path:"blog/page:num"。不是使用根文件夹中的默认index.html作为分页器模板,而是使用/blog/index.html。分页器将根据需要生成类似/blog/page2/和/blog/page3/的页面。这将使您到达yourwebsite.com/b

  9. ruby - 实现k最近邻需要哪些数据? - 2

    我目前有一个reddit克隆类型的网站。我正在尝试根据我的用户之前喜欢的帖子推荐帖子。看起来K最近邻或k均值是执行此操作的最佳方法。我似乎无法理解如何实际实现它。我看过一些数学公式(例如k表示维基百科页面),但它们对我来说并没有真正意义。有人可以推荐一些伪代码,或者可以查看的地方,以便我更好地了解如何执行此操作吗? 最佳答案 K最近邻(又名KNN)是一种分类算法。基本上,您采用包含N个项目的训练组并对它们进行分类。如何对它们进行分类完全取决于您的数据,以及您认为该数据的重要分类特征是什么。在您的示例中,这可能是帖子类别、谁发布了该项

  10. ruby-on-rails - 使用 Ruby 正确处理 Stripe 错误和异常以实现一次性收费 - 2

    我查看了Stripedocumentationonerrors,但我仍然无法正确处理/重定向这些错误。基本上无论发生什么,我都希望他们返回到edit操作(通过edit_profile_path)并向他们显示一条消息(无论成功与否)。我在edit操作上有一个表单,它可以POST到update操作。使用有效的信用卡可以正常工作(费用在Stripe仪表板中)。我正在使用Stripe.js。classExtrasController5000,#amountincents:currency=>"usd",:card=>token,:description=>current_user.email)

随机推荐