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

如何用SvelteKit和Supabase实现DOM实时更新?

实现SvelteKit + Supabase提交表单后实时更新DOM

你的问题核心是当前仅在组件初始化时获取一次数据,提交新内容后没有触发本地数据更新,导致DOM无法实时刷新。下面提供两种实用解决方案:

方案一:手动更新本地数据(简单场景适用)

将数据存储在Svelte响应式变量中,提交成功后直接更新该变量触发DOM刷新:

<script>
    import { supabase } from '$lib/supabaseClient'
    import { onMount } from 'svelte'

    // 用响应式变量存储数据,替代一次性await调用
    let scores = [];

    const getData = async () => {
        const { data, error } = await supabase.from('scores').select('*')
        if (!error) scores = data;
    }

    // 组件挂载时加载初始数据
    onMount(() => getData());

    let newRowName = '';
    let newRowScore = 0;
    const postData = async (nameVal, scoreVal) => {
        // 插入时添加.select(),获取刚插入的数据
        const { data: insertedData, error } = await supabase
            .from('scores')
            .insert([{ name: nameVal, score: scoreVal }])
            .select()

        if (!error) {
            // 更新响应式数组,触发DOM自动更新
            scores = [...scores, ...insertedData];
            // 清空表单
            newRowName = '';
            newRowScore = 0;
        }
    }
</script>

{#if scores.length === 0}
    <p>Waiting...</p>
{:else}
    {#each scores as singleData}
        <p>{singleData.name}: {singleData.score}</p>
    {/each}
{/if}

<form on:submit|preventDefault={() => postData(newRowName, newRowScore)}>
    <label for="name">Name:</label>
    <input type="text" id='name' bind:value={newRowName} required />
    <label for="score">Score:</label>
    <input type="number" id='score' bind:value={newRowScore} required />

    <button>Add row</button>
</form>

方案二:Supabase实时订阅(多用户协作场景适用)

利用Supabase的Realtime功能,监听表的INSERT事件,自动同步所有客户端的变更:

<script>
    import { supabase } from '$lib/supabaseClient'
    import { onMount, onDestroy } from 'svelte'

    let scores = [];
    let subscription; // 存储订阅实例,用于销毁时清理

    const getData = async () => {
        const { data, error } = await supabase.from('scores').select('*')
        if (!error) scores = data;
    }

    onMount(async () => {
        await getData(); // 加载初始数据

        // 订阅scores表的INSERT事件
        subscription = supabase.channel('public:scores')
            .on('postgres_changes', 
                { event: 'INSERT', schema: 'public', table: 'scores' },
                (payload) => {
                    // 将新插入的行添加到数组
                    scores = [...scores, payload.new];
                }
            )
            .subscribe()
    })

    // 组件销毁时取消订阅,避免内存泄漏
    onDestroy(() => {
        if (subscription) supabase.removeChannel(subscription);
    })

    let newRowName = '';
    let newRowScore = 0;
    const postData = async (nameVal, scoreVal) => {
        const { error } = await supabase
            .from('scores')
            .insert([{ name: nameVal, score: scoreVal }])

        if (!error) {
            newRowName = '';
            newRowScore = 0;
        }
    }
</script>

{#if scores.length === 0}
    <p>Waiting...</p>
{:else}
    {#each scores as singleData}
        <p>{singleData.name}: {singleData.score}</p>
    {/each}
{/if}

<form on:submit|preventDefault={() => postData(newRowName, newRowScore)}>
    <label for="name">Name:</label>
    <input type="text" id='name' bind:value={newRowName} required />
    <label for="score">Score:</label>
    <input type="number" id='score' bind:value={newRowScore} required />

    <button>Add row</button>
</form>

注意:使用Realtime前,需在Supabase控制台的「Realtime」选项卡中,启用public schema下scores表的INSERT事件权限。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 21:57:32