Svelte Store美元赋值与原生方法的差异及表单提交异常分析
问题分析:SvelteKit表单提交时Store状态未更新的问题
场景与代码
我正在使用SvelteKit与TypeScript构建表单,通过Svelte Store管理用户输入状态并封装到模块中,相关代码如下:
useFormInput.svelte
<script lang="ts" context="module"> import {writable, get} from "svelte/store" type Form = { name: string, job: string, home: string, gender: string } export const useFormInput = () => { const form = writable<Form>({ name: "", job: "", home: "", gender: "" }) const onChange = <T extends string = keyof Form>(key: T, value: T extends keyof Form ? Form[T] : never) => { const _form = get(form) form.set({ ..._form, [key]: value }) } return {form, onChange} } </script>
useFormSubmit.svelte
<script lang="ts" context="module"> import {writable} from "svelte/store" type Form = { name: string, job: string, home: string, gender: string } type Props = { form: Form } export const useFormSubmit = (props: Props) => { const isLoading = writable(false) const onSubmit = async () => { isLoading.set(true) await new Promise((resolve) => { setTimeout(() => { resolve(null!) }, 3000) }) console.log(props.form, "form submitted") isLoading.set(false) } return {onSubmit, isLoading} } </script>
问题描述
useFormInput返回form store对象及使用set方法更新store的onChange函数,useFormSubmit接收store的form值作为参数并返回提交触发函数。填写表单后提交时,控制台显示form store仍为初始空值{name: "", job: "", home: "", gender: ""},但使用美元赋值($form)替代onChange时,表单内容能正常显示。想了解二者是否存在未知差异?
问题根源
你在调用useFormSubmit时,传递的是Store初始化时的快照值,而不是Store对象本身。当后续通过onChange更新Store时,useFormSubmit内部的props.form还是最初传入的那个静态对象,不会自动同步Store的最新状态。
而$form是Svelte的语法糖,它会自动订阅Store的变化:
- 读取
$form时拿到的是Store的最新值 - 修改
$form(比如$form.name = 'xxx')本质上是直接更新Store内部的当前值,同时触发组件和订阅者的更新
解决方法
修改useFormSubmit,让它接收Store对象而非快照值,提交时再获取Store的最新状态:
修改后的useFormSubmit.svelte
<script lang="ts" context="module"> import {writable, get} from "svelte/store" type Form = { name: string, job: string, home: string, gender: string } // 改为接收Store对象类型 type Props = { form: ReturnType<typeof writable<Form>> } export const useFormSubmit = (props: Props) => { const isLoading = writable(false) const onSubmit = async () => { isLoading.set(true) await new Promise((resolve) => { setTimeout(() => { resolve(null!) }, 3000) }) // 提交时获取Store的最新值 const latestForm = get(props.form) console.log(latestForm, "form submitted") isLoading.set(false) } return {onSubmit, isLoading} } </script>
组件中调用方式
在使用的组件里,直接传入Store对象form,而非快照值$form:
const { form, onChange } = useFormInput(); const { onSubmit, isLoading } = useFormSubmit({ form });
补充说明
- 你自己实现的
onChange逻辑本身没有问题,它确实通过set方法正确更新了Store状态 - 问题核心在于提交时没有从Store中获取最新值,而是依赖了初始化时的静态快照
内容的提问来源于stack exchange,提问作者nw.lee
相关产品推荐
相关产品推荐

