Vue3+Ts封装简易pagenation组件实现分页功能

效果图:

新建components/Pagenation.vue

结构:

<template>
  <div class="my-pagination">
    <a
      :class="{disabled: currentPage === 1}"
      href="javascript:"
      @click="changePage(false)"
    >上一页</a>
    <a
      v-if="currentPage > 4"
      :class="{active: currentPage === 1}"
      href="javascript:"
      @click="changePage(1)"
    >{{
      1
    }}</a>
    <span v-if="currentPage > 4">...</span>

    <template
      v-for="item in list"
      :key="item"
    >
      <a
        v-if="(currentPage < pages - 3 && item !== pages-1) || (currentPage > 4 && item !== 3)"
        :class="{active: currentPage === item}"
        href="javascript:;"
        @click="changePage(item)"
      >{{
        item
      }}</a>
      <a
        v-if="!(currentPage < pages - 3) && !(currentPage > 4)"
        :class="{active: currentPage === item}"
        href="javascript:;"
        @click="changePage(item)"
      >{{
        item
      }}</a>
    </template>
    <span v-if="currentPage < pages - 3">...</span>
    <a
      v-if="currentPage < pages - 3"
      :class="{active: currentPage === pages}"
      href="javascript:;"
      @click="changePage(pages)"
    >{{ pages }}</a>
    <a
      :class="{disabled: currentPage === pages}"
      href="javascript:"
      @click="changePage(true)"
    >下一页</a>
  </div>
</template>

逻辑:

import {computed, ref, watch} from 'vue';

const props = defineProps<{ total: number, pageSize: number, page?: number }>();
const emits = defineEmits(['change-page']);

// 动态计算中期的页码信息
// 每页的条数
// const pageSize = 8
// 总页数
const pages = computed(() => Math.ceil(props.total / props.pageSize));
// 当前页码
const currentPage = ref(props.page || 1);
watch(() => props.page, (newVal) => {
  currentPage.value = newVal;
});
// 动态计算页码列表
const list = computed(() => {
  // 当父组件传递total的值发生变化时,计算属性会重新计算
  // pages = Math.ceil(props.total / props.pageSize)
  const result = [];
  // 总页码小于等于5;大于5
  if (pages.value <= 5) {
    // 总页码小于等于5的情况
    for (let i = 1; i <= pages.value; i++) {
      result.push(i);
    }
  } else {
    // 总页码大于5
    if (currentPage.value <= 2) {
      // 左侧临界值
      for (let i = 1; i <= 5; i++) {
        result.push(i);
      }
    } else if (currentPage.value >= pages.value - 1) {
      // 右侧临界值
      for (let i = pages.value - 4; i <= pages.value; i++) {
        result.push(i);
      }
    } else {
      // 中间的状态
      for (let i = currentPage.value - 2; i <= currentPage.value + 2; i++) {
        result.push(i);
      }
    }
  }
  return result;
});
// 控制上一页和下一页变化
const changePage = (type: any) => {
  if (type === false) {
    // 上一页
    // 页面是第一页时,禁止点击操作
    if (currentPage.value === 1) {
      return;
    }
    if (currentPage.value > 1) {
      currentPage.value -= 1;
    }
  } else if (type === true) {
    // 下一页
    // 页面是最后页时,禁止点击操作
    if (currentPage.value === pages.value) {
      return;
    }
    if (currentPage.value < pages.value) {
      currentPage.value += 1;
    }
  } else {
    // 点击页码
    currentPage.value = type;
  }
  emits('change-page', currentPage.value);
};

样式:

.my-pagination {
  display: flex;
  justify-content: flex-end;

  > a {
    display: inline-block;
    padding: 5px 10px;
    text-decoration: none;
    color: #666;
    border-radius: 4px;
    background: #f0f2f5;
    margin-right: 10px;

    &:hover {
      color: #c40000;
    }

    &.active {
      background: #c40000;
      color: #fff;
      border-color: #c40000;
    }

    &.disabled {
      cursor: not-allowed;
      opacity: 0.4;

      &:hover {
        color: #333;
      }
    }
  }

  > span {
    margin-right: 10px;
  }
}

使用:

<script lang="ts" setup>
import Pagenation from '@/components/Pagenation.vue';
import { getList } from '@/api/home'
import type { HomeListItem, HomeListReq } from '@/typings/home'

const list = ref<HomeListItem[]>([]);

const pageParams = ref<HomeListReq>({
  page: 1,
  pageSize: 10,
});

const total = ref(0);

// 获取数据
const getData = async () => {
    const {data} = await getList(pageParams.value);
    list.value = data.records;
    total.value = data.total;
}

// 页码改变
const changePage = async (page: number) => {
  pageParams.value.page = page;
  getData()
};
</script>

<template>
   ...
  <Pagenation
    :page="pageParams.page"
    :page-size="pageParams.pageSize"
    :total="total"
    @change-page="changePage"
   />    
</template>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值