Vue3后台管理系统(十八)分页组件

目录

一、场景效果

二、滑动工具类

三、组件封装

四、全局注册

五、使用案例


一、场景效果

 

二、滑动工具类

在src/utils文件夹下新建scroll-to.ts

// src/utils/scroll-to.ts
const easeInOutQuad = (t: number, b: number, c: number, d: number) => {
  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
const requestAnimFrame = (function () {
  return (
    window.requestAnimationFrame ||
    (window as any).webkitRequestAnimationFrame ||
    (window as any).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
 */
const move = (amount: number) => {
  document.documentElement.scrollTop = amount;
  (document.body.parentNode as HTMLElement).scrollTop = amount;
  document.body.scrollTop = amount;
};

const position = () => {
  return (
    document.documentElement.scrollTop ||
    (document.body.parentNode as HTMLElement).scrollTop ||
    document.body.scrollTop
  );
};

/**
 * @param {number} to
 * @param {number} duration
 * @param {Function} callback
 */
export const scrollTo = (to: number, duration: number, callback?: any) => {
  const start = position();
  const change = to - start;
  const increment = 20;
  let currentTime = 0;
  duration = typeof duration === 'undefined' ? 500 : duration;
  const animateScroll = function () {
    // increment the time
    currentTime += increment;
    // find the value with the quadratic in-out easing function
    const val = 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();
};

三、组件封装

在src/components文件夹下新建Pagination文件夹,并在Pagination文件夹下新建index.vue

<!--src/components/Pagination/index.vue-->
<template>
  <div :class="{ hidden: hidden }" class="pagination-container">
    <el-pagination
      :background="background"
      v-model:current-page="currentPage"
      v-model:page-size="pageSize"
      :layout="layout"
      :page-sizes="pageSizes"
      :total="total"
      @size-change="handleSizeChange"
      @current-change="handleCurrentChange"
    />
  </div>
</template>

<script setup lang="ts">
import { computed, PropType } from 'vue';
import { scrollTo } from '@/utils/scroll-to';

const props = defineProps({
  total: {
    required: true,
    type: Number as PropType<number>,
    default: 0
  },
  page: {
    type: Number,
    default: 1
  },
  limit: {
    type: Number,
    default: 20
  },
  pageSizes: {
    type: Array as PropType<number[]>,
    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
  }
});

const emit = defineEmits(['update:page', 'update:limit', 'pagination']);

const currentPage = computed<number | undefined>({
  get: () => props.page,
  set: value => {
    emit('update:page', value);
  }
});

const pageSize = computed<number | undefined>({
  get() {
    return props.limit;
  },
  set(val) {
    emit('update:limit', val);
  }
});

function handleSizeChange(val: number) {
  emit('pagination', { page: currentPage, limit: val });
  if (props.autoScroll) {
    scrollTo(0, 800);
  }
}

function handleCurrentChange(val: number) {
  currentPage.value = val;
  emit('pagination', { page: val, limit: props.limit });
  if (props.autoScroll) {
    scrollTo(0, 800);
  }
}
</script>

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

.pagination-container.hidden {
  display: none;
}
</style>

四、全局注册

// src/main.ts
import Pagination from '@/components/Pagination/index.vue';
app
    .component('Pagination', Pagination)
    .mount('#app')

五、使用案例

<!--src/App.vue-->
<script setup lang="ts">
import Pagination from '@/components/Pagination/index.vue'
import {onMounted, reactive} from "vue";

const state = reactive({
  loading: true,
  queryParams: {
    pageNum: 1,
    pageSize: 10
  },
  dataList: [] as Data[],
  total: 0,
});

interface Data {
  id: number
  name: string
}

function handleQuery() {
  state.loading = true;
  state.dataList = [
    {id: 1,name: '张三'},
    {id: 2, name: '李四'},
  ];
  state.total = 1000;
  state.loading = false;
}

onMounted(()=>{
  handleQuery()
})

</script>

<template>
  <div>
    <div v-for="data in state.dataList" :key="data.id">
      <div>
        编码:{{ data.id }}
      </div>
      <div>
        姓名:{{ data.name }}
      </div>
    </div>
    <div>
      <pagination
          v-if="state.total > 0"
          :total="state.total"
          v-model:page="state.queryParams.pageNum"
          v-model:limit="state.queryParams.pageSize"
          @pagination="handleQuery"
      />
    </div>
  </div>
</template>

<style>

</style>

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

文子阳

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值