You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.07 05:57:03