【发布时间】:2018-08-02 13:46:22
【问题描述】:
React 新手的一个常见问题是为什么双向数据绑定不是内置功能,通常的回答包括对单向数据流的解释以及双向数据绑定并不总是可取的想法出于性能原因。这是我想更详细了解的第二点。
我目前正在为apollo-link-state(来自 Apollo 的新客户端状态管理工具)开发一个表单库。这个概念与 redux-form 非常相似,只是使用 apollo-link-state 而不是 redux 作为状态管理器。 (请注意,表单状态与域实体的状态分开存储,尽管可以选择使用实体来填充表单的初始状态。)
当用户对表单进行更改时,库会立即通过onChange 处理程序更新存储。我正在考虑允许单个字段选择退出该行为,以防程序员担心性能,但后来我开始想知道这何时会成为真正的性能问题。无论如何,浏览器都会触发oninput 事件,所以我能想到的唯一性能考虑是商店是否会随着用户输入而更新。当然,执行突变会产生额外的开销,而不仅仅是调用setState(),但这实际上只是几个额外的函数调用。假设我没有使用 apollo,而只是调用一个直接更新一些全局存储的函数 - 那么性能考虑是什么?
我的想法是,如果表单要支持在用户在一个字段中键入时立即更新表单状态,那么它也可能对所有字段都这样做。用户一次只能输入一个字段,我看不到使页面有时在某些字段上更快(可能可以忽略不计)而有时在其他字段上变慢的好处。此外,我的库允许消费者使用他们想要的任何输入组件,所以如果程序员只是想要更少的状态更新,他们可以编写一个组件来消除 React 的 onChange 事件或使用浏览器自己的 change 或 blur 事件而是。
我在这里遗漏了什么吗?在用户提交表单之前,我的图书馆的用户是否希望忽略特定字段的更改还有其他原因?或者也许更有用的选项是忽略对整个表单的更改(直到提交)?
这是我当前方法背后的基本概念的基本(非常简化)说明:
// defined in a globally-accessible module
const formState = {
// This somehow causes any dependent form components to re-render
// when state changes
update(formName, updatedState) {
...
}
}
export default formState
...
// UserForm.js:
export default class UserForm extends PureComponent {
componentDidMount() {
formState.userForm = {
firstName: '',
lastName: '',
}
}
handleChange(e) {
const { target } = e
formState.update('userForm', { [target.name]: target.value })
}
//...
render() {
const { userForm } = formState
return (
<form onSubmit={this.handleSubmit}>
<label for="name">Name</label>
<input id="name" type="text" onChange={this.handleChange} value={userForm.name} />
<label for="email">Email</label>
<input id="email" type="email" onChange={this.handleChange} value={userForm.email} />
</form>
)
}
}
最后,为了完整起见,我应该提一下,其中还涉及一些 API 设计注意事项。如果我不提供选择退出自动 2 向绑定的选项,则单个输入组件的设计可能会稍微简单一些。如果有人感兴趣,我可以发布详细信息。
【问题讨论】:
标签: javascript performance reactjs flux