Vue.js로 개발을 하는데 디자인 역량이 부족하다 싶으면 적당한 UI 라이브러리를 잘 써야 그나마 볼 만한 인터페이스를 만들 수 있습니다. 그 때 쓸 수 있는 툴 가운데 하나가 Vuetify입니다.
Vuetify에서 표를 표현하고 싶을 때 많이 사용하는 게 v-data-table 컴포넌트인데요, 이 컴포넌트를 쓰다 보면 컴포넌트의 특정 행을 클릭해서 다른 라우트로 넘어갔다가 다시 원래 v-data-table 컴포넌트를 보여주는 라우트로 돌아오는 상황이 자주 생길 수 있습니다. (마치 게시판에서 게시물 목록에 있는 특정 게시물을 클릭해서 내용을 보고는 이전 페이지 아이콘을 클릭해서 게시물 목록으로 돌아오는 것처럼 말이죠.) 이 때 표의 원래 페이지로 돌아가는 게 자연스러운데, v-data-table의 기본 설정을 그대로 사용한다면 항상 첫 페이지로 되돌아가게 됩니다.
이 문제를 해결하기 위해서는 사용자가 특정 행을 클릭해서 다른 화면으로 넘어가기 전에 미리 페이지 정보를 어딘가에 저장해야 합니다. 이렇게 서로 다른 뷰로 넘어가더라도 상태를 유지할 때 쓸 수 있는 게 Pinia 저장소입니다. Pinia 저장소에 currentPage라는 이름으로 페이지 정보를 저장하도록 합시다.
다음과 같은 식으로 stores/dataTableStore.js라는 파일을 만들어 줍니다.
// stores/dataTableStore.js
import { defineStore } from 'pinia';
export const useDataTableStore = defineStore('dataTable', {
state: () => ({
currentPage: 1
}),
actions: {
setCurrentPage(page) {
this.currentPage = page;
}
}
});
그리고 뷰 라우터에서
테이블을 보여주는 컴포넌트는 다음과 같은 식으로 구성하면 됩니다.
<template>
<v-data-table
:items="items"
:page="page"
:items-per-page="5"
@update:page="updatePage"
></v-data-table>
</template>
<script>
import { useDataTableStore } from '@/stores/dataTableStore';
import { onMounted, ref, watch } from 'vue';
import { useRoute } from 'vue-router';
export default {
setup() {
const store = useDataTableStore();
const page = ref(store.currentPage);
const route = useRoute();
const updatePage = (newPage) => {
// 라우트가 활성화된 후에만 페이지 업데이트
if (route.meta.isActivated) {
page.value = newPage;
store.setCurrentPage(newPage);
}
};
onMounted(() => {
// 라우트 활성화 플래그 설정
route.meta.isActivated = true;
page.value = store.currentPage;
});
return {
items,
page,
updatePage
};
}
};
</script>
컴포넌트가 마운트될 때 매번 페이지를 업데이트하는 로직이 실행되면 이 컴포넌트에서 다른 컴포넌트로 갔다가 다시 이 컴포넌트로 돌아올 때 무조건 currentPage가 1로 초기화되는 문제가 생기기 때문에 이 문제를 해결하기 위해 route.meta.isActivated라는 플래그를 활용합니다. (onMounted 이벤트 처리부에서 route.meta.isActivated를 참으로 설정하고, 이 플래그가 활성화된 이후에만 페이지를 업데이트하는 거죠.)