SvelteKit 远程函数 变通助手
发布: (2025年12月8日 GMT+8 07:48)
3 min read
原文: Dev.to
Source: Dev.to
如果你和我一样,已经等了很久很久才等到 SvelteKit 的 Remote Functions——它们真的很棒!虽然仍然是实验性的,但它们节省的时间是无价的。下面列出了当前的限制、解决办法以及它们的状态。
1. Submit Type
你可能想在组件模板之外声明 enhance 函数。在表单动作中你会这样使用类型:
import type { SubmitFunction } from '@sveltejs/kit';
const onSubmit: SubmitFunction = async ({ formElement }) => {
// …
};
没有直接的 SubmitFunction 导入方式,所以可以这样推导:
type SubmitRemoteFunction = Parameters[0];
const onSubmit: SubmitRemoteFunction = async ({ submit }) => {
try {
await submit();
} catch (error) {
console.error(error);
}
};
2. Form Data
formData 不会自动传递,但可以自行推导:
const onSubmit: SubmitRemoteFunction = async ({ submit, form }) => {
const formData = new FormData(form);
// 可选的转换
const data = Object.fromEntries(formData);
// 其实不需要这样做,因为所有内容都在表单 rune 本身可用,但谁知道呢…
};
3. Set Initial Data
文档建议使用 fields.set,但这不是动态的,可能导致 state_referenced_locally 错误。它也不会在后续更改时自动更新值。解决办法是创建一个在水合后重新初始化表单的辅助函数:
export function initForm(init: () => void) {
init();
let hydrated = false;
$effect(() => {
if (!hydrated) {
hydrated = true;
return;
}
init();
});
}
用法
initForm(() =>
updateChapterAccessForm.fields.set({
courseId: initialData.course_id,
chapterId: initialData.id,
isFree: !!initialData.is_free
})
);
4. Form Debug
一个小型辅助组件,用于在开发期间打印当前表单数据(类似 SuperForms,但使用 runes):
import type { RemoteFormFields, RemoteFormInput, RemoteForm } from '@sveltejs/kit';
const { form }: { form: RemoteForm } = $props();
const fields = $derived(form.fields as RemoteFormFields);
{JSON.stringify(
{
values: fields.value(),
issues: fields.allIssues()
},
null,
2
)}
使用方式
<!-- 在此处插入组件用法 -->
没有 issue tracker;这只是一个开发工具。
5. Touched
目前没有内置的 touched 或 pristine 状态。下面的钩子用于跟踪整个表单是否被修改过:
import type { RemoteForm, RemoteFormInput } from "@sveltejs/kit";
export const useTouched = (
form: RemoteForm
) => {
const initialValue = JSON.stringify(form.fields.value());
return {
get touched() {
return JSON.stringify(form.fields.value()) !== initialValue;
}
};
};
用法
const touchForm = useTouched(myForm);
const isSubmitting = $derived(!!myForm.pending);
const isValid = $derived(!myForm.fields.allIssues() && touchForm.touched);
// touchForm.touched
目前就这些。欢迎分享你发现的其他解决方案!