SvelteKit静态博客实现按客户端当前日期过滤文章
kit: { adapter: adapter(), }
}
#### +layout.ts ```typescript export const prerender = true;
BlogPosts.svelte
<script> export let posts: BlogPost[]; </script> <section> <ul class="posts"> {#each posts as post} <li class="post"> <a href={post.slug} class="title">{post.title}</a> ... </li> {/each} </ul> </section>
+page.svelte
<script> export let data; </script> <BlogPostList posts={data.postsAsOfToday} />
+page.ts
export async function load({ fetch }) { // 接口返回仓库中所有markdown文件对应的博客文章 const response = await fetch(base + '/api/blog'); const posts: BlogPost[] = await response.json(); const dateToday = new Date(); const postsAsOfToday = posts.filter((post) => new Date(post.date) <= dateToday); return { postsAsOfToday }; }
尝试过但无效的写法
<!-- BlogPosts.svelte --> {#each posts as post} {#if new Date(post.date) <= new Date()} ... {/if} {/each}
解决方案
完全可以实现客户端运行时过滤,同时保持静态博客的属性。核心逻辑是:把所有文章数据打包进静态文件,让浏览器加载页面时,用客户端的当前日期实时过滤内容,而非在构建阶段就剔除未到发布日期的文章。
1. 修改+page.ts,返回全部文章
移除构建阶段的过滤逻辑,直接返回所有文章,确保所有内容都被预渲染到静态资源中:
// +page.ts export async function load({ fetch }) { const response = await fetch('/api/blog'); const posts: BlogPost[] = await response.json(); // 不再在构建时过滤,返回所有文章 return { allPosts: posts }; }
2. 调整组件逻辑,在客户端实时过滤
先修改+page.svelte,把全部文章传给组件:
<!-- +page.svelte --> <script> export let data; </script> <BlogPosts posts={data.allPosts} />
再修改BlogPosts.svelte,用Svelte的响应式变量触发客户端实时判断:
<!-- BlogPosts.svelte --> <script> export let posts: BlogPost[]; // 响应式变量,每次页面加载/刷新时获取客户端当前日期 $: currentDate = new Date(); </script> <section> <ul class="posts"> {#each posts as post} {#if new Date(post.date) <= currentDate} <li class="post"> <a href={post.slug} class="title">{post.title}</a> <!-- 其他文章内容 --> </li> {/if} {/each} </ul> </section>
3. 保留静态预渲染配置
保持svelte.config.js和+layout.ts的原有配置不变,确保博客仍为静态预渲染模式:
// svelte.config.js import adapter from '@sveltejs/adapter-static'; const config = { // 其他原有配置 kit: { adapter: adapter(), } } export default config;
// +layout.ts export const prerender = true;
为什么之前的尝试无效?
之前在BlogPosts.svelte中直接加判断没生效,是因为Svelte预渲染时会在构建阶段执行模板逻辑,生成静态HTML时就把未到发布日期的文章过滤掉了。现在通过打包所有文章数据,并使用响应式变量$: currentDate = new Date(),确保每次页面加载时都会用浏览器的当前日期重新过滤内容。
额外提示
- 确保文章的
date字段是合法格式(如YYYY-MM-DD),否则new Date(post.date)无法正确解析。 - 如果担心未发布文章的内容被用户通过查看源代码看到,可以把文章正文放在单独的路由中,仅当用户点击已发布的文章链接时才加载对应内容。
内容的提问来源于stack exchange,提问作者Dimebag
相关产品推荐
相关产品推荐

