SvelteKit动态路由[symbol].svelte切换URL后组件未重渲染数据不更新
问题原因及修复方案
核心问题1:动态路由页面变量声明上下文错误
你将props、symbolName这类组件实例变量声明在了context="module"的脚本块中,该上下文的所有变量是全局单例,所有组件实例共享同一份数据,不会随着路由切换重新初始化,且组件实例无法响应这类变量的变更。同时你没有在普通组件脚本块中接收load函数返回的props,子组件拿到的一直是第一次初始化的旧数据。
核心问题2:搜索组件状态声明上下文错误
search.svelte中的selectedOption、handleOnChange属于组件内部状态,你错误将它们放在了context="module"块中,导致状态全局共享,跳转逻辑会出现异常。
修复代码
1. 修正 [symbol].svelte
<script context="module"> import StockSymbol from '$lib/stocks/index.svelte'; import data from '../../../static/symbols.json'; export const hydrate = true export async function load({ page, fetch }) { const symbolName = page.params.symbol; let symbols = data.symbols; let symbolFound = symbols.find(s => s.s.toLowerCase() === page.params.symbol.toLowerCase()); if (!symbolFound) { return { status: 302, redirect: '/404' } } const url = `APIHOST/${symbolName}`; const res = await fetch(url); let stock = await res.json(); stock = stock.data.attributes; return { props: { stock, symbolName } } } </script> <!-- 新增普通组件脚本块,接收load返回的响应式props --> <script> export let stock; export let symbolName; </script> <svelte:head> <title>Stock: { symbolName || ''}</title> </svelte:head> <!-- 直接传递响应式props到子组件 --> <StockSymbol {stock}/>
2. 修正 search.svelte
去掉script标签的context="module"属性,让状态属于组件实例本身:
<!-- 移除context="module" --> <script> import AutoComplete from "simple-svelte-autocomplete"; import data from '../../../static/symbols.json'; import { goto, prefetch } from '$app/navigation'; var options = data; let selectedOption; const handleOnChange = () => { console.log(selectedOption); if (selectedOption) { goto(`/stocks/${selectedOption.s.toLowerCase()}`, {replaceState: true}); } } </script> <!-- 原有模板代码保持不变 --> <div class="min-w-0 hidden sm:block flex-1 md:px-8 lg:px-48 xl:col-span-6"> <div class="flex items-center px-6 py-4 md:max-w-3xl md:mx-auto lg:max-w-none lg:mx-0 xl:px-0"> <div class="w-full"> <label for="search" class="sr-only">Search</label> <div class="relative"> <div class="z-20 pointer-events-none absolute inset-y-1 left-0 pl-3 flex items-center"> <svg class="h-5 w-5 text-gray-400" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true"> <path fill-rule="evenodd" d="M8 4a4 4 0 100 8 4 4 0 000-8zM2 8a6 6 0 1110.89 3.476l4.817 4.817a1 1 0 01-1.414 1.414l-4.816-4.816A6 6 0 012 8z" clip-rule="evenodd"></path> </svg> </div> <AutoComplete onChange={handleOnChange} inputId="search" placeholder="Search" className="w-full text-md" inputClassName="block px-10 py-2 w-full rounded-md border border-gray-300 text-sm placeholder-gray-500 focus:outline-none focus:text-gray-900 focus:placeholder-gray-400 focus:ring-1 focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm" items={data.symbols.map(o => o)} labelFunction={o => o.s + '. ' + o.n} bind:selectedItem={selectedOption} hideArrow={true} showClear={true} showLoadingIndicator={true} noResultsText="No Results Found" maxItemsToShowInList="10" localFiltering=false /> </div> </div> </div> </div>
修改完成后路由切换时load函数会重新执行,新的props会响应式更新到子组件,UI就会正常刷新了。
内容的提问来源于stack exchange,提问作者arifCoder
相关产品推荐
相关产品推荐

