qiniu / formstate-x

Manage state of form with ease.
https://qiniu.github.io/formstate-x
MIT License
33 stars 10 forks source link

Opt-in debouncing #63

Closed nighca closed 2 years ago

nighca commented 2 years ago

备注

为什么调整 dirty 的定位(从基于值的比较改为记录状态)。

本来我们这样判断 dirty:如果当前值(value)与初始值(initialValue)“相同”,则认为 dirty: false,否则为 true。这里的关键是,如何判定“相同”;其逻辑是这样的:

因此对于 FieldStateFormState / ArrayFormState,都会有:

state.dirty // false
state.onChange(state.initialValue)
state.dirty // false

但是对于 DeouncedStateTransformedState(即这个 PR 中的 ProxyState),(几乎)无法去正确地实现一个满足上述要求的 dirtyWith

以某个 DeouncedState 实例 s 为例,s.values.$.value 更新,通过 s.$.dirtyWith(s.initialValue) 得到的是 s.$.values.initialValue 是否“相同”,而无法得出 s.values.initialValue 是否相同;注意,因为 s 不关心 s.$ 具体是什么 state class,只知道它是实现了 IState 接口的实例,因此 s 也不具备应该怎么比较 s.values.initialValue 的知识。

再以某个 TransformedState 实例 s 为例,调用 s.$.dirtyWith 前它需要先对 initialValue 进行转换,而对同一个值的两次转换可能得到两个引用不相等的转换结果;因此如果 s.$ 是个 FieldState,即便当前 s.values.initialValue 是引用相等的,因为其转换后结果不一定引用相等,因此 s.$.dirtyWith 的结果可能不准确。

综上,基于值的比较来判定 dirty 的做法在新的背景下不可持续(它要求 state 与其使用者更高程度的耦合)。这里将 dirty 的定位调整为:

If value has been touched.

即,值是否被设置过,无论设置后的值与初始值是否一致

不过这个 PR 中对具体实现的调整并不彻底,这里只调整了 FormState (& ArrayFormState) 的 dirty 实现,FieldState 的实现暂时没有调整(还是直接判断 valueinitialValue 是否引用相等)。

在 #74 中我们会将 FieldStatedirty 行为调整为与上述定位一致