如何用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」选项卡中,启用
publicschema下scores表的INSERT事件权限。
内容的提问来源于stack exchange,提问作者user19738598
相关产品推荐
相关产品推荐

