<template>
<main class="container">
<section>
<h1>FAQ</h1>
<p>서비스 이용에 불편함이 있으시면 빠르게 도와드리겠습니다.</p>
</section>
<section>
<div>
<USearch v-model="searchFilter" border-style @search="searchText = searchFilter" @reset="searchFilter = ''" />
<div class="tabs">
<button :class="data.find((item) => item.isActive) ? '' : 'is-active'" @click="resetActive">전체</button>
<button v-for="item in data" :key="item.id" :class="{ 'is-active': item.isActive }" @click="activeTab(item)">
{{ item.category }}
</button>
</div>
</div>
</section>
<section>
<UPagination
:data="activeContents"
:data-option="{ currentPage: faqData.tablePage, pageSize: faqData.pageSize }"
:is-hide-pagination="activeContents.length === 0"
@onPageChange="onPageChange"
>
<template #data="{ data }">
<div v-if="!data || !data[0]">
<p>리스트가 없습니다.</p>
</div>
<div v-for="(item, index) in data" :key="index">
<details>
<summary>
<dl>
<dd>{{ item.category }}</dd>
<dt>{{ item.questions }}</dt>
</dl>
</summary>
<div>{{ item.asked }}</div>
</details>
</div>
</template>
</UPagination>
</section>
</main>
</template>
[
{
"id": 1,
"category": "카테고리1",
"content": [
{
"category": "카테고리1",
"questions": "카테고리1 FAQ입니다.",
"asked": "답변"
},
]
},
{
"id": 2,
"category": "카테고리2",
"content": [
{
"category": "카테고리2",
"questions": "카테고리2 FAQ입니다.",
"asked": "답변"
},
]
},
{
"id": 3,
"category": "카테고리3",
"content": [
{
"category": "카테고리3",
"questions": "카테고리3 FAQ입니다.",
"asked": "답변"
}
]
},
{
"id": 4,
"category": "카테고리4",
"content": []
},
{
"id": 5,
"category": "카테고리5",
"content": [
{
"category": "회원",
"questions": "회원 FAQ입니다.",
"asked": "답변"
},
]
}
]
asyncData() {
const data = cloneDeep(FaqJson);
data.forEach((item) => {
item.isActive = false;
});
return { data };
},
data() {
return {
data: null,
searchText: '',
searchFilter: '',
};
},
methods: {
searchFilters(item) {
return (
item.questions.toUpperCase().includes(this.searchText.toUpperCase()) ||
item.asked.toUpperCase().includes(this.searchText.toUpperCase())
);
},
resetActive() {
this.data.forEach((item) => {
item.isActive = false;
});
},
activeTab(item) {
this.resetActive();
item.isActive = true;
},
}
computed: {
activeContents() {
return (
this.data.find((item) => item.isActive)?.content.filter(this.searchFilters) ??
this.data.reduce((pre, cur) => {
pre.push(...cur.content.filter(this.searchFilters));
return pre;
}, [])
);
}
},
문제점 : 검색 시 tab 전체 메뉴로 이동을 해야하는데 이동하지않고 해당 active 된 텝에서
검색이 이루어지며, 페이지네이션 이동할 시 초기화해주는 page 값을 초기화하는걸 넣어주지 않아 제대로 된 출력이 되지 않고있었음.
✅ 검색 시 tab 전체 메뉴로 이동을 해야하는데 이동하지않고 해당 active 된 텝에서
검색이 이루어지지 않는 문제는 검색과 초기화를 함수로 분리하여 해결
✅ 페이지네이션 이동할 시 초기화해주는 page 값을 초기화하는걸 넣어주지 않아 제대로 된 출력이 되지 않고있던 문제는 activeTab에 tablePage 값을 0으로 만들어주는것을 추가
<USearch v-model="searchFilter" border-style @search="searchText = searchFilter" @reset="searchFilter = ''" />
<!--수정-->
<USearch v-model="searchFilter" border-style @search="onSearch" @reset="onReset" />
computed: {
activeContents() {
const isAll = !this.data.find((item) => item.isActive);
return this.data
.reduce((pre, cur) => {
if (isAll) {
pre.push(...cur.content);
} else if (cur.isActive) {
pre.push(...cur.content);
}
return pre;
}, [])
.filter(this.searchFilters);
}
},
methods: {
onSearch() {
this.resetActive();
this.searchText = this.searchFilter;
},
searchFilters(item) {
return (
item.questions.toUpperCase().includes(this.searchText.toUpperCase()) ||
item.asked.toUpperCase().includes(this.searchText.toUpperCase())
);
},
onReset() {
this.searchFilter = '';
this.searchText = '';
this.resetActive();
},
resetActive() {
this.data.forEach((item) => {
item.isActive = false;
});
},
activeTab(item) {
this.resetActive();
item.isActive = true;
this.faqData.tablePage = 0;
},
onPageChange(page) {
this.faqData.tablePage = page;
}
}