【问题标题】:Controlled vs uncontrolled components in ReactReact 中的受控组件与非受控组件
【发布时间】:2017-06-10 08:48:07
【问题描述】:

几乎在每个 ReactJS 教程中,甚至在 the official documentation 中处理输入更改,都推荐使用 onChange。我们对值使用状态并通过 onChange 更改它。这会在每个击键中触发渲染。所以,

  1. 渲染真的那么便宜吗?
  2. 输入值是否未保存在 DOM 中?所以 DOM 和 VirtualDOM 之间没有区别,所以虽然渲染发生了,但没有任何变化? (可能是错误的假设)。

出于娱乐和学习的目的,我尝试了这些:

  1. 使用自定义函数和变量来保存值,设置上次输入后的状态,而不是每次击键,传递与值相关的组件等。
  2. 使用 onBlur 而不是 onChange。

但是,我不喜欢他们中的任何一个,并想问这个问题。如果实时输入值变化对我们来说并不重要,我们只关心最后一个输入,仍然 onChange 是要走的路吗?

【问题讨论】:

    标签: javascript reactjs


    【解决方案1】:

    React 非常有效地处理重新渲染。它只重新渲染更改。

    有两种配置输入的方法

    第一:受控输入

    对于受控输入,您通常使用状态变量(在某些情况下甚至是道具)来指定输入的值。在这种情况下,您需要调用 onChange 函数来设置状态(或道具),因为值被设置为状态/道具,您需要更改它以更改值,否则它将保持不变。

    前

    <input value={this.state.textVal} onChange={(e) => this.setState({textVal: e.target.value}) />
    

    具有受控输入的优点是您可以在整个 React 组件中使用该值,并且您不需要在输入上触发事件或访问 DOM 来获取该值。

    第二:不受控制的输入

    在这种情况下,您不需要 onChange 处理程序来获取输入,因为您没有为输入指定自定义值。输入的值可以通过访问 dom 或从事件对象中获取

    例如:

    <input type="text" onBlur={(e) => {console.log(e.target.value)}/>
    

    获取输入值的另一种方法是访问 DOM,我们使用 refs as this.inputVal.value

    关于如何使用 ref,请参阅此答案:

    In React .js: is there any function similar like document.getElementById() in javascript ? how to select certain object?

    关于 React virtualDOM 的问题

    虚拟 DOM 用于高效地重新渲染 DOM。这实际上与脏检查您的数据无关。您可以使用带或不带脏检查的虚拟 DOM 重新渲染。计算两个虚拟树之间的差异有一些开销,但虚拟 DOM 差异是关于了解 DOM 中需要更新的内容,而不是您的数据是否已更改。

    只有在状态发生变化时才会重新渲染虚拟树。因此,使用 observable 检查状态是否已更改是防止不必要的重新渲染的有效方法,这会导致大量不必要的树差异。

    【讨论】:

    • 我错过了文档中不受控制的部分,感谢您指出这一点。正如我所见,使用 ref 这很容易。但是,在您回答和@squegeim 对“单一真相来源”的解释之后我看到 onChange 是要走的路。最后一件事,因为我是一名学习者,你能给我看一份关于使用关于这个主题的 observable 的“文档”吗?
    • 我当然会接受它。说 observable 是指不受控制的组件?
    • 不,你应该使用受控组件,有一个链接与受控组件相同的文档。
    • 我现在已经在使用受控组件,我只是问了这个问题以便更好地理解。我只是不明白你的回答中“使用可观察对象......”的部分。
    • 如果您指的是虚拟树,它表示为防止重新渲染而进行的脏检查
    【解决方案2】:

    对我来说,除了实时验证之外,使用受控组件的主要原因是“单一事实来源”的原则。

    在不受控制的组件的情况下,表单输入和 React 组件中使用的输入值可能不同。您可以获取新值onBlur,但有一些方法可以在不发出此事件的情况下更改 DOM 中的值,在这种情况下,用户看到的值和您正在处理的值可能会有所不同,从而导致与用户期望的结果不同。

    这可能不是一个大问题,但由于 React 经常宣扬这一原则(比如不在状态中保留可以从其他状态派生的值),我只是为了保持一致性而这样做。

    此外,您无需担心重新渲染每个输入的成本。

    【讨论】:

    • 感谢您提醒我真相的单一来源。在我成为开发人员的过程中,我真的应该经常记住这一点 :) 对于一个非常非常大的应用程序,重新渲染仍然不是问题?或者开发人员用其他东西解决这个问题?像@Shubham Khatri 的可观察建议,还是在 React 的生命周期中,或其他方式?
    猜你喜欢
    • 1970-01-01
    • 2017-07-20
    • 2019-02-11
    • 2019-09-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多