假设我有一个blog
路由,可以加载所有博客文章的完整数组。个别博客文章直播在blog/[postId]
.有没有一种工兵惯用法将单个帖子的数据从blog
传递到blog/[postId]
?
从本质上讲,如果您在blog
我想预加载用于显示blog/[postId]
的代码。然后,当您单击指向blog/[postId]
的链接时,立即导航到该链接并显示来自blog
的数据。但是,当然,如果您直接导航到blog/[postId]
那么仍然应该调用preload()
。
prefetch
并没有完全做到这一点,因为这仍然需要网络请求。我还尝试了检查商店的预加载,除非网络请求为空,否则不会发出网络请求,但你不能在<script context="module">
中使用商店。
感谢您的评论@three这使我找到了答案。
如果路由或_layout
组件导出preload()
,则始终在导航时调用它。因此,我最终通过将获取的数据存储在第二个参数中来做到这一点preload()
,该参数通常称为session
,并且似乎在所有组件之间共享。而且我只在数据不存在时才打电话给this.fetch()
。
<!-- blog/index.svelte -->
<script context="module">
export async function preload (page, session) {
let {posts} = session;
if (undefined === posts) {
const response = await this.fetch('blog/posts.json');
posts = await response.json();
session.posts = posts
}
return {posts}
}
</script>
<script>
export let posts;
</script>
{#each posts as post}
<!-- ... -->
{/each}
然后在[slug].svelte
检查您要查找的帖子session.posts
,如果不存在,请加载它。
<!-- blog/[slug].svelte -->
<script context="module">
export async function preload (page, session) {
const {slug} = page.params
const {posts} = session
let post
if (undefined === posts) {
const response = await this.fetch(`blog/${slug}.json`)
post = await response.json()
} else {
post = posts.find(p => p.slug === slug)
}
if (undefined === post) {
this.error(404, "Sorry we couldn't find that post")
}
return {post}
}
</script>
<script>
export let post
</script>
<!-- ... render post -->
现在导航是即时的。为了获得最终的健壮性,您可以添加检查以在数据过时时(例如超过 5 分钟,等等(重新加载。
编辑
实际上,您本身不需要使用会话。如果您只想使session
参数preload(page, session)
不undefined
则可以在server.js
中使用它:
sapper.middleware({
// Define session parameter as an empty object
session: (req, res) => ({})
})