目录
一、场景效果
二、滑动工具类
在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>