v3 composition api paginate
by dapo
HTML
<script src="https://gistcdn.githack.com/dasDaniel/f3cebc1274339055729c6e887ca8d2ad/raw/32f92b584f2f1df6aff813d75684dc38a666f32e/vue.global.js"></script>
<div id="app"></div>
<template id="appTemplate">
<div>
<div>
<div class="paginate-item" v-for="i in pagin8.range" :style="{width:(100/pagin8.pageSize)+'%'}">{{i}}</div>
</div>
<div style="text-align:center;">
<button @click="pagin8.gotoFirst">◄◄</button>
<button @click="pagin8.gotoPrev">◄</button>
{{pagin8.currentPageNum}} / {{pagin8.numPages}}
<button @click="pagin8.gotoNext">►</button>
<button @click="pagin8.gotoLast">►►</button>
</div>
Page Size: <input v-model="pagin8.pageSize" type="number">
<pre>{{ {pageSize: pageSize, currentIndex: pagin8.currentIndex, currentPageNum: pagin8.currentPageNum, total: pagin8.total, numPages: pagin8.numPages, range: pagin8.range} }}</pre>
</div>
</template>
CSS
body {
font-family: Verdana, Arial, Helvetica, sans-serif;
}
.paginate-item{
display: inline-block;
width: 25%;
box-sizing: border-box;
border: 1px solid #CCC;
padding: 10px;
margin: 0 0 10px 0;
}
button {
width: 42px;
height: 42px;
border-radius: 4px;
border: 1px solid #eee;
margin: 2px;
box-shadow: 2px 2px 2px #ccc;
background-color: #f9f9f9;
color: #555;
transition: all 0.125s;
}
button:hover {
box-shadow: 1px 1px 1px #bbb;
background-color: #eee;
color: #000;
transition: all 0.125s;
}
JavaScript
const {
reactive,
computed,
ref,
onMounted,
watch,
isRef
} = Vue;
/**
*
* @param {Object} options
* @param {ref|number} options.pageSize
* @param {ref|number} options.currentIndex 0 based index
* @param {ref|array} options.array
*/
const pagin8r = options => {
// setup props
const pageSize = isRef(options.pageSize)
? options.pageSize
: ref(options.pageSize);
const currentIndex = isRef(options.currentIndex)
? options.currentIndex
: ref(options.currentIndex);
const array = isRef(options.array) ? options.array : ref(options.array);
// create computed
const total = computed(() => array.value.length);
const currentPageNum = computed(() => currentIndex.value + 1);
const numPages = computed(() => Math.ceil(total.value / pageSize.value));
const range = computed(() =>
array.value.slice(
currentIndex.value * pageSize.value,
(currentIndex.value + 1) * pageSize.value
)
);
// create methods
const gotoNext = () => {
currentIndex.value = Math.min(currentIndex.value + 1, numPages.value - 1);
};
const gotoPrev = () => {
currentIndex.value = Math.max(0, currentIndex.value - 1);
};
const gotoFirst = () => {
currentIndex.value = 0;
};
const gotoLast = () => {
currentIndex.value = numPages.value - 1;
};
// return props, computed, and method variables
return {
array,
pageSize,
currentIndex,
currentPageNum,
total,
numPages,
range,
gotoNext,
gotoPrev,
gotoFirst,
gotoLast
};
};
const App = {
template: document.getElementById("appTemplate").innerHTML,
setup() {
// create an array
let array = [...Array(50)].map((x, n) => n);
let pageSize = ref(4);
let currentIndex = 0;
// setup/config the pagination functionality
const pagin8 = pagin8r({
pageSize,
currentIndex,
array
});
// pass entire pagination to template
return {
pagin8,
pageSize
};
}
};
const app =...