본문 바로가기
Framework/Vue

Vue3 pagination component

by 행복한 기린님 2022. 11. 29.

 

페이지네이션이 필요해서 만들까 ui-framework를 사용해서 가져다 쓸까 하다가

 

지금조차 직접 만들지 않는다면 앞으로는 누가 만든 것을 계속 가져다 쓸 것이고

마음에 안들거나 기능 커스텀이 불가능하거나 스타일 수정이 안되는 등 가져다 쓸 수 없는 상황이 온다면

 

나는 이 간단한 기능 조차 구현할 수 없을 것만 같다는 생각이 들어 직접 구현했다.

vuetify를 사용했어도 됐으나 직접 하고 싶은 마음이 컸다.

 

많은 사람들이 써줬으면 하는 마음에 코드를 공개하겠습니다.

/* Pagination.vue */

<template>
    <nav class="pagination">
        <RouterLink to="" v-for="text in previous" @click="changePage(text)">{{ text }}</RouterLink>
        <!-- 페이징 첫 부분 -->
        <template v-if="data.page < nums + 1">
            <RouterLink to="" v-for="text in data.limit" :class="{ active : text === data.page}" @click="changePage(text)">{{ text }}</RouterLink>
        </template>
        <!-- 페이징 중간 부분 -->
        <template v-if="data.page >= nums + 1 && data.page < data.total - (nums-1)">
            <RouterLink to="" v-for="text in data.limit" :class="{ active : data.page + text - (nums+1) === data.page}" @click="changePage(data.page + text - (nums+1))">{{ data.page + text - (nums+1) }}</RouterLink>
        </template>
        <!-- 페이징 끝 부분 -->
        <template v-if="data.page <= data.total && data.page >= data.total - (nums-1)">
            <RouterLink to="" v-for="text in data.limit" :class="{ active : data.total + text - data.limit === data.page}" @click="changePage(data.total + text - data.limit)">{{ data.total + text - data.limit }}</RouterLink>
        </template>
        <RouterLink to="" v-for="text in next" @click="changePage(text)">{{ text }}</RouterLink>
    </nav>
</template>
<script setup>
const previous = ['<<'];
const next = ['>>'];
const props = defineProps({
    data: Object,
})

const nums = Math.floor(props.data.limit / 2);

const emit = defineEmits(['paging'])

const changePage = (text) => {
    switch(true){
        case text === '<<':
            props.data.page = 1;    
            emit('paging', props.data);
            break;
        case text === '>>':
            props.data.page = props.data.total;
            emit('paging', props.data);
            break;
        default :
            props.data.page = text;
            emit('paging', props.data);
            break;
    }
}
</script>

<style lang="scss" scoped src="./Pagination.scss"></style>
/* Pagination.scss */

@import '@/assets/css/variables.scss';
@import '@/assets/css/mixin.scss';

.pagination {
    display: flex;
    justify-content: center;
    align-items: center;
    column-gap: 20px;

    a {
        display: flex;
        justify-content: center;
        align-items: center;
        width: 40px;
        height: 40px;
        padding: 8px;
        font-size: 14px;
        color: rgb(126, 126, 126);
        background-color: $background--color;
        transition: background-color 0.6s, color 0.6s;

        &:hover {
            color: white;
            background-color: #525252;
            transition: background-color 0.6s, color 0.6s;
        }
    }

    a.active {
        color: white;
        background-color: #525252;
        transition: background-color 0.6s, color 0.6s;
    }
}

 

부모 컴포넌트에서 사용법이 궁금하다면 아래 코드를 추가하세요.

/* Student.vue */

<template>
    <h1>학생</h1>
    <Pagination :data="pageData" @paging="changePage"></Pagination>
</template>

<script setup>
import Pagination from '../../components/pagination/Pagination.vue';
import { reactive } from 'vue';

const pageData = reactive({
  page: 1,
  limit: 5,
  total: 12,
})

const changePage = (data) => {
  console.log(data);
  pageData.page = data.page;  
}

</script>
<style lang="scss" scoped src="./Student.scss"></style>

 

댓글