手动实现elementPlus分页组件

手动实现elementPlus分页组件

徐徐
前端
发布于2024-08-13 23:02:04
🌺前言
一个基本实现elementPlus的分页一样的效果

vue
<template>
  <ul
    v-if="pageCount > 1"
    class="xu-pagination__wrap flex">
    <li
      v-if="pageCount > 0"
      class="lx-pagination__button"
      :class="{ disabled: currentPage === 1 }"
      @click="lastPage">
      <i class="iconfont icon-shangyiye" />
    </li>
    <li
      class="xu-pagination-pager"
      :class="{ active: currentPage === 1 }"
      @click="pageChange(1)">
      1
    </li>
    <li
      v-if="showPrevMore"
      class="xu-pagination-pager dot"
      @mouseenter="onMouseEnter(true)"
      @mouseleave="quickPrevHover = false"
      @focus="onFocus(true)"
      @blur="quickPrevFocus = false">
      <i
        v-if="quickPrevHover || quickPrevFocus"
        class="iconfont icon-arrowleftdl"
        @click="lastGroupPage" />
      <i
        v-else
        class="iconfont icon-gengduo" />
    </li>
    <li
      v-for="item in pagers"
      :key="item"
      class="xu-pagination-pager"
      :class="{ active: currentPage === item }"
      @click="pageChange(item)">
      {{ item }}
    </li>
    <li
      v-if="showNextMore"
      class="xu-pagination-pager dot"
      @mouseenter="onMouseEnter(false)"
      @mouseleave="quickNextHover = false"
      @focus="onFocus(false)"
      @blur="quickNextFocus = false">
      <i
        v-if="quickNextHover || quickNextFocus"
        class="iconfont icon-youshuangjiantou"
        @click="nexGroupPage" />
      <i
        v-else
        class="iconfont icon-gengduo" />
    </li>
    <li
      v-if="pageCount > 1"
      class="xu-pagination-pager"
      :class="{ active: currentPage === pageCount }"
      @click="pageChange(pageCount)">
      {{
        pageCount }}
    </li>
    <li
      v-if="pageCount > 0"
      class="lx-pagination__button"
      :class="{ disabled: currentPage === pageCount }"
      @click="nextPage">
      <i class="iconfont icon-xiayiye" />
    </li>
  </ul>
</template>
<script lang="ts" setup>
const props = defineProps({
  total: {
    type: [Number, String],
    default: 0,
  },
  pageNo: {
    type: Number,
    default: 0,
  },
  pageSize: {
    type: Number,
    default: 0,
  },
  pagerCount: {
    type: Number,
    default: 7,
  },
});

const emit = defineEmits(["update:page-no", "update:page-size", "change"]);
const currentPage = computed<number>({
  set(val) {
    emit("update:page-no", val);
  },
  get() {
    return props.pageNo;
  },
});
const size = computed<number>({
  set(val) {
    emit("update:page-size", val);
  },
  get() {
    return props.pageSize;
  },
});
const { pagerCount, total } = toRefs(props);
const totalCount = computed(() => Number(total.value))
/**
 * 总的页数
 */
const pageCount = computed(() => Math.max(1, Math.ceil(totalCount.value / size.value)))
/**
 * 除去第一页和最后一页
 */
const middlePagerCount = computed(() => pagerCount.value - 2)
/**
 * 分页按钮数量的一半
 */
const halfPagerCount = computed(() => (pagerCount.value - 1) / 2)
const quickPrevHover = ref(false)
const quickNextHover = ref(false)
const quickPrevFocus = ref(false)
const quickNextFocus = ref(false)
/**
 * 是否展示左边的点点点
 */
const showPrevMore = computed(() => {
  if (pageCount.value <= pagerCount.value) return false
  if (currentPage.value > pagerCount.value - halfPagerCount.value) return true
  return false
})
/**
 * 是否展示右边的点点
 */
const showNextMore = computed(() => {
  if (pageCount.value <= pagerCount.value) return false
  if (currentPage.value < pageCount.value - halfPagerCount.value) return true
  return false
})

/**
 * 中间的分页按钮页码
 */
const pagers = computed(() => {
  const array: number[] = []
  if (showPrevMore.value && !showNextMore.value) {
    const startPage = pageCount.value - (pagerCount.value - 2)
    for (let i = startPage; i < pageCount.value; i++) {
      array.push(i)
    }
  } else if (!showPrevMore.value && showNextMore.value) {
    for (let i = 2; i < pagerCount.value; i++) {
      array.push(i)
    }
  } else if (showPrevMore.value && showNextMore.value) {
    const offset = Math.floor(pagerCount.value / 2) - 1
    for (let i = currentPage.value - offset; i <= currentPage.value + offset; i++) {
      array.push(i)
    }
  } else {
    for (let i = 2; i < pageCount.value; i++) {
      array.push(i)
    }
  }
  return array
})
const onMouseEnter = (foword: boolean) => {
  if (foword) {
    quickPrevHover.value = true
  } else {
    quickNextHover.value = true
  }
}
const onFocus = (foword: boolean) => {
  if (foword) {
    quickPrevFocus.value = true
  } else {
    quickNextFocus.value = true
  }
}
/**
 * 页码改变
 */
const pageChange = (i: number) => {
  if (i === currentPage.value) return;
  currentPage.value = i;
  emit("change");
};
/**
 * 上一页
 */
const nextPage = () => {
  const i = Math.min(currentPage.value + 1, pageCount.value);
  pageChange(i);
};
/**
 * 下一页
 */
const lastPage = () => {
  const i = Math.max(currentPage.value - 1, 1);
  pageChange(i);
};
/**
 * 上一组
 */
const lastGroupPage = () => {
  const i = Math.max(currentPage.value - middlePagerCount.value, 1)
  pageChange(i)
}
/**
 * 下一组
 */
const nexGroupPage = () => {
  const i = Math.min(currentPage.value + middlePagerCount.value, pageCount.value)
  pageChange(i)
}
</script>
<style lang="scss" scoped>
.xu-pagination__wrap {
  gap: 10px;

  li {
    list-style: none;
    cursor: pointer;

    &.dot .iconfont {
      display: block;
      width: 100%;
      height: 100%;
    }
  }

  a {
    background-color: var(--xu-main-border-color);
    display: inline-block;
  }

}

.xu-pagination-pager {
  min-width: 31px;
  height: 31px;
  text-align: center;
  line-height: 31px;
  padding: 0 4px;
  background-color: var(--xu-main-border-color);
  border-radius: 3px;
  color: var(--xu-muted-2-color);

  &.active {
    color: #fff;
    background-color: var(--xu-theme);
    cursor: default;
  }

  &:not(.active):hover {
    opacity: 0.8;
    color: var(--xu-theme);
  }

}

.lx-pagination__button {
  text-align: center;
  line-height: 31px;
  height: 31px;
  min-width: 31px;
  padding: 0 4px;
  background-color: var(--xu-main-border-color);
  border-radius: 3px;
  color: var(--xu-muted-2-color);

  .iconfont {
    font-size: 12px;
  }

  &.disabled {
    cursor: not-allowed;
  }
}
</style>
文章最后更新于 2024-08-28 00:45:30
留言
头像
徐徐作者2024-08-17 12:46:40
回复

基本还原了elementPlus分页的核心功能

头像
xiaoke2024-08-29 22:17:02
回复

页面都出不来

~~到底了