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

页面销毁时,Svelte类内的Store是否需手动取消订阅?

问题解答

核心结论

必须手动取消ListController实例中listData的订阅,否则会引发内存泄漏,导致实例和内部store无法被正常销毁。

原因分析

  • 页面销毁时,+page.svelte组件内的userGroupList实例会失去组件层面的引用,但类内部的unsubscribe是listData store的订阅回调:
    • 该回调持有对ListController实例的引用(通过this访问hasSelection)
    • listData store又持有对该回调的引用
    • 这种循环引用会阻止垃圾回收机制回收实例和store,导致它们长期驻留在内存中。
  • Svelte的自动取消订阅仅针对组件模板或script中使用$store语法、以及在组件生命周期内显式创建的订阅(可通过onDestroy自动清理),类内部自行创建的订阅不在自动处理范围内。

解决方案

  1. 给ListController添加销毁方法,用于取消订阅并清理资源:
import { writable, get } from 'svelte/store';

export default class ListController {
    listData = writable([]);
    hasSelection = writable(false);

    unsubscribe = this.listData.subscribe((listDataValue) => {
        this.hasSelection.set(
            listDataValue.some(item => item.selected === true)
        );
    });

    // 添加销毁方法
    destroy() {
        this.unsubscribe();
        // 可选:清空store数据,加速资源回收
        this.listData.set([]);
        this.hasSelection.set(false);
    }
}
  1. 在+page.svelte的onDestroy钩子中调用实例的销毁方法:
<script>
    import { onDestroy } from 'svelte';
    import ListTable from '$lib/Components/ListTable.svelte';
    import ListController from '$lib/Classes/ListController';
    
    let userGroupList = new ListController();
    let { listData, hasSelection } = userGroupList; // 修正原代码中hasChanged的笔误

    onDestroy(() => {
        userGroupList.destroy();
    });
</script>

<ListTable {listData} />
<button disabled={!$hasSelection}>Delete list entry</button> <!-- 修正禁用逻辑:无选中时禁用按钮 -->

补充说明

如果不手动取消订阅,每次页面加载都会创建新的ListController实例,旧实例和store因循环引用无法被回收,内存占用会持续增加,长期运行会降低应用性能。

内容的提问来源于stack exchange,提问作者ArchibaldTuttle

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 07:52:29