게시물 이동 로딩 후 진입으로 복귀
This commit is contained in:
@@ -9,17 +9,10 @@ const route = useRoute()
|
||||
const slug = computed(() => String(route.params.slug || ''))
|
||||
|
||||
/**
|
||||
* SSR 직접 접속은 본문을 먼저 받아 SEO를 유지하고, 클라이언트 내부 이동은 즉시 화면을 전환한다.
|
||||
* 본문은 블로킹으로 받아 로딩 표시 후 완성된 화면으로 전환한다.
|
||||
* 이전·다음 글은 상세 응답에 포함되어 별도 목록 요청 없이 표시된다.
|
||||
*/
|
||||
const {
|
||||
data: fetchedPost,
|
||||
pending: isPostPending,
|
||||
error: postFetchError
|
||||
} = await useFetch(() => `/api/posts/${slug.value}`, {
|
||||
lazy: import.meta.client,
|
||||
default: () => null
|
||||
})
|
||||
const { data: post } = await useFetch(() => `/api/posts/${slug.value}`)
|
||||
const { data: tags } = useLazyFetch('/api/tags?tagType=all', {
|
||||
default: () => []
|
||||
})
|
||||
@@ -29,15 +22,7 @@ const { data: siteSettings } = useLazyFetch('/api/site-settings', {
|
||||
})
|
||||
const postToc = useState('post-detail-toc', () => [])
|
||||
|
||||
const post = computed(() => (
|
||||
fetchedPost.value?.slug === slug.value
|
||||
? fetchedPost.value
|
||||
: null
|
||||
))
|
||||
|
||||
const isPostLoading = computed(() => isPostPending.value || (!post.value && !postFetchError.value))
|
||||
|
||||
if (import.meta.server && !post.value) {
|
||||
if (!post.value) {
|
||||
throw createError({
|
||||
statusCode: 404,
|
||||
statusMessage: '게시물을 찾을 수 없습니다.'
|
||||
@@ -148,17 +133,6 @@ onMounted(() => {
|
||||
fetchCurrentViewer()
|
||||
})
|
||||
|
||||
watch([isPostPending, postFetchError, post], () => {
|
||||
if (!import.meta.client || isPostPending.value || post.value) {
|
||||
return
|
||||
}
|
||||
|
||||
showError(createError({
|
||||
statusCode: postFetchError.value?.statusCode || 404,
|
||||
statusMessage: '게시물을 찾을 수 없습니다.'
|
||||
}))
|
||||
})
|
||||
|
||||
watchEffect(() => {
|
||||
postToc.value = tableOfContents.value
|
||||
})
|
||||
@@ -279,7 +253,6 @@ useHead(() => ({
|
||||
|
||||
<template>
|
||||
<div class="post-detail">
|
||||
<template v-if="post">
|
||||
<section class="mt-6 mb-8">
|
||||
<div class="mx-auto flex max-w-[720px] flex-col gap-2.5 px-4 sm:px-5">
|
||||
<h1 class="text-xl font-semibold leading-[1.125] sm:text-2xl">
|
||||
@@ -547,49 +520,5 @@ useHead(() => ({
|
||||
</div>
|
||||
</div>
|
||||
</Transition>
|
||||
</template>
|
||||
|
||||
<section v-else class="post-detail__loading mt-6 mb-12" aria-live="polite" aria-busy="true">
|
||||
<div class="mx-auto flex min-h-[70vh] max-w-[720px] flex-col gap-5 px-4 sm:px-5">
|
||||
<div class="grid gap-3">
|
||||
<div class="post-detail__loading-shimmer h-8 w-11/12 rounded bg-[var(--site-panel-strong)] sm:h-10" />
|
||||
<div class="post-detail__loading-shimmer h-4 w-2/5 rounded bg-[var(--site-panel-strong)]" />
|
||||
</div>
|
||||
<div class="border-b border-[var(--site-line)] pb-4">
|
||||
<div class="post-detail__loading-shimmer h-3 w-3/5 rounded bg-[var(--site-panel-strong)]" />
|
||||
</div>
|
||||
<div class="post-detail__loading-shimmer aspect-video w-full rounded-[10px] bg-[var(--site-panel-strong)]" />
|
||||
<div class="mt-4 grid gap-3">
|
||||
<div class="post-detail__loading-shimmer h-4 w-full rounded bg-[var(--site-panel-strong)]" />
|
||||
<div class="post-detail__loading-shimmer h-4 w-[94%] rounded bg-[var(--site-panel-strong)]" />
|
||||
<div class="post-detail__loading-shimmer h-4 w-[88%] rounded bg-[var(--site-panel-strong)]" />
|
||||
<div class="post-detail__loading-shimmer h-4 w-[96%] rounded bg-[var(--site-panel-strong)]" />
|
||||
<div class="post-detail__loading-shimmer h-4 w-[72%] rounded bg-[var(--site-panel-strong)]" />
|
||||
</div>
|
||||
<span class="sr-only">{{ isPostLoading ? '게시물을 불러오는 중입니다.' : '게시물을 표시할 수 없습니다.' }}</span>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.post-detail__loading-shimmer {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.post-detail__loading-shimmer::after {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
content: '';
|
||||
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.42), transparent);
|
||||
transform: translateX(-100%);
|
||||
animation: post-detail-loading-shimmer 1.2s ease-in-out infinite;
|
||||
}
|
||||
|
||||
@keyframes post-detail-loading-shimmer {
|
||||
to {
|
||||
transform: translateX(100%);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user