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

如何在Svelte Store更新前校验修改值?避免二次更新

解决Svelte Store更新前校验导致两次更新的问题

当使用数字输入框绑定Svelte Store属性时,输入非法值(如-1)会导致Store先更新为错误值,再被反应式语句修正为正确值,触发两次Store更新。以下是几种解决方法:

方案一:使用本地变量+手动校验更新

通过本地变量绑定输入框,在变量变化时先完成校验修正,再更新Store,确保Store只接收正确值:

<script>
    import { availableTrainingMaterials } from '$stores';
    
    let t1Value = $availableTrainingMaterials.T1;
    
    $: {
        // 确保值不小于0
        const correctedValue = Math.max(t1Value, 0);
        // 只有值变化时才更新Store
        if (correctedValue !== $availableTrainingMaterials.T1) {
            availableTrainingMaterials.update(store => {
                store.T1 = correctedValue;
                return store;
            });
        }
        // 同步输入框显示修正后的值
        t1Value = correctedValue;
    }
</script>

<div class="available-materials">
    <h2>我拥有的材料:</h2>
    <div>
        T1: <input bind:value={t1Value} type="number" />
    </div>
</div>

方案二:自定义带校验逻辑的Store

把校验逻辑封装到Store内部,任何更新操作都会自动经过校验,从根源避免错误值进入Store:

修改Store.js:

import { writable } from 'svelte/store';

function createMaterialsStore() {
    const { subscribe, set, update } = writable({ T1: 0 });
    
    return {
        subscribe,
        // 自定义更新T1的方法,内置校验
        updateT1: (newValue) => {
            const correctedValue = Math.max(newValue, 0);
            update(store => {
                store.T1 = correctedValue;
                return store;
            });
        },
        // 带校验的整体设置方法
        set: (newStore) => {
            const correctedStore = {
                ...newStore,
                T1: Math.max(newStore.T1, 0)
            };
            set(correctedStore);
        }
    };
}

export const availableTrainingMaterials = createMaterialsStore();

修改Materials.svelte:

<script>
    import { availableTrainingMaterials } from '$stores';
    
    let t1Value = $availableTrainingMaterials.T1;
    
    // 输入变化时调用自定义更新方法
    $: availableTrainingMaterials.updateT1(t1Value);
</script>

<div class="available-materials">
    <h2>我拥有的材料:</h2>
    <div>
        T1: <input bind:value={t1Value} type="number" />
    </div>
</div>

方案三:通过输入事件直接处理

监听输入框的input事件,在事件回调中完成值的校验修正,再更新Store:

<script>
    import { availableTrainingMaterials } from '$stores';
    
    function handleInput(e) {
        let value = Number(e.target.value);
        // 校验修正值
        value = Math.max(value, 0);
        // 更新Store
        availableTrainingMaterials.update(store => {
            store.T1 = value;
            return store;
        });
        // 同步输入框显示正确值
        e.target.value = value;
    }
</script>

<div class="available-materials">
    <h2>我拥有的材料:</h2>
    <div>
        T1: <input value={$availableTrainingMaterials.T1} type="number" on:input={handleInput} />
    </div>
</div>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 06:50:22