SvelteKit同路由新API请求后客户端页面数据不更新问题
SvelteKit搜索页面路由更新后客户端数据不刷新问题解决
问题详情
我在Navbar中设置了搜索输入框,提交后跳转到search/[searchTerm]页面。该页面的+page.server.ts会将动态路由参数作为搜索词调用API,并在+page.svelte中展示获取到的数据。
但遇到了问题:当已处于search/[searchTerm]页面并展示数据时,再次执行搜索,+page.server.ts的load函数会重新运行,动态路由参数已更新,服务器也获取到了新数据,但客户端页面仍显示第一次搜索的结果。尝试用$:让页面数据响应式无效;尝试响应式解构$: ({ items } = data.results.albums)时,items返回undefined。
相关代码
+page.server.ts
export const load: ServerLoad = async ({ params }) => { const searchTerm: string | undefined = params.searchTerm; const fetchSearchResults = async (searchTerm: string | undefined) => { const response = await getSearchResults(searchTerm); const results = await response.json(); // console.log(results.albums.items); return results; }; return { results: fetchSearchResults(searchTerm) }; };
+page.svelte 脚本部分
<script lang="ts"> export let data: PageData; const { items } = data.results.albums; const albums = items.slice(0, 10).map((album: any) => ({ artist: album.artists.map((_artist: any) => _artist.name).join(', '), songUrl: album.external_urls.spotify, title: album.name, coverImage: album.images[2].url })); </script>
Navbar搜索输入框代码
<form action={`/search/${searchTerm.split(' ').join('+')}`}> <input bind:value={searchTerm} type="text" placeholder="Search…" /> <button type="submit"> Search </button> </form>
问题原因
- 页面初始化时的
items和albums计算是一次性执行的,没有监听data的变化,路由更新后不会重新计算。 - 直接解构
data.results.albums时,未考虑异步数据加载的时序问题,路由更新时data.results可能还未完成解析,导致items为undefined。 - 原表单的action属性是静态拼接的,输入框内容变化时可能无法实时更新,影响路由跳转的准确性。
解决方案
1. 优化服务端load函数,确保返回解析完成的数据
显式await异步操作,避免潜在的时序问题:
// +page.server.ts export const load: ServerLoad = async ({ params }) => { const searchTerm = params.searchTerm; // 处理空搜索词的边界情况 if (!searchTerm) { return { results: { albums: { items: [] } } }; } const response = await getSearchResults(searchTerm); const results = await response.json(); return { results }; };
2. 在客户端页面添加响应式数据处理
用$:标记响应式语句,确保data更新时重新计算展示数据,同时添加可选链避免报错:
<script lang="ts"> export let data: PageData; // 响应式监听data变化,安全获取items $: items = data?.results?.albums?.items || []; // 响应式生成展示用的albums数据 $: albums = items.slice(0, 10).map((album: any) => ({ artist: album.artists.map((_artist: any) => _artist.name).join(', '), songUrl: album.external_urls.spotify, title: album.name, coverImage: album.images[2]?.url // 可选链防止图片数组越界 })); </script>
3. 优化Navbar的搜索提交逻辑
改用SvelteKit的goto方法进行客户端路由跳转,确保路由更新能正确触发页面数据刷新:
<script lang="ts"> import { goto } from '$app/navigation'; let searchTerm = ''; const handleSubmit = (e: Event) => { e.preventDefault(); if (!searchTerm.trim()) return; // 编码搜索词,处理特殊字符 const encodedTerm = encodeURIComponent(searchTerm); goto(`/search/${encodedTerm}`); }; </script> <form on:submit={handleSubmit}> <input bind:value={searchTerm} type="text" placeholder="Search…" /> <button type="submit">Search</button> </form>
内容的提问来源于stack exchange,提问作者gariepyG
相关产品推荐
相关产品推荐

