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);
    }
};

Issue Tracker

2. Form Data

formData 不会自动传递,但可以自行推导:

const onSubmit: SubmitRemoteFunction = async ({ submit, form }) => {
    const formData = new FormData(form);
    // 可选的转换
    const data = Object.fromEntries(formData);
    // 其实不需要这样做,因为所有内容都在表单 rune 本身可用,但谁知道呢…
};

Issue Tracker

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
    })
);

Issue Tracker

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

目前没有内置的 touchedpristine 状态。下面的钩子用于跟踪整个表单是否被修改过:

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

Issue Tracker


目前就这些。欢迎分享你发现的其他解决方案!

Back to Blog

相关文章

阅读更多 »