我的背景是WPF/Winforms,我刚刚开始学习React。根据我的理解,每次按键时,以下代码都会重新渲染,因此将重新生成包括文本框在内的元素。因此旧的文本框被丢弃并创建一个新的文本框(失去焦点)。
那么如果旧的文本框具有焦点,并且在我按下某个键后创建了一个新的文本框,那么新的文本框如何仍然具有焦点?
有趣的是,当我用谷歌搜索这个时,人们似乎经历了我所期望的,因为每次按键后你都必须重新聚焦文本框。但对我来说,它似乎神奇地起作用。
我猜React在这里更聪明一点并且回收了元素?或者它仍在重新创建一个新的文本框,但在幕后恢复焦点?
function App() {
const [userText, setUserText] = useState("empty")
return (
<>
<p>{userText}</p>
<input type='text' value={userText} onChange={e => setUserText(e.target.value)}/>
</>
)
}
export default App
我猜 React 在这里更聪明一点并且回收 元素?或者它仍在重新创建一个新的文本框,但正在恢复 幕后焦点?
也许这个问题的答案就包含在问题本身中。
重点是 React 绝对不会在代码中重新创建输入元素。即使“回收”这个词也可能“有点不准确”。最合适的术语可能是update,React 在这种情况下更新元素。 之所以说问题有答案,问题是说React正在幕后恢复焦点。然而,这里有一个问题是,最新重新渲染返回的最新 JSX 没有任何有关元素焦点的信息,它不携带任何有关它的信息。那么 React 从哪里获取要恢复焦点的信息呢?除了从元素本身获取它之外没有其他方法。这意味着元素本身 - 及其所有属性和值,都保留在 DOM 中,因此无需执行任何额外操作即可保留焦点。
现在关于这里发生的每一次击键。状态
userText正在更新。由于这是状态更新,因此组件将在每次击键时重新渲染。然而,每次击键新返回的每个 JSX 与之前的 JSX 的区别仅在于 props value。 value 属性将继续获取该状态的最新文本。因此,为了将最新的 JSX 与相应的 DOM 元素同步,它只需要“更新”同一输入 DOM 元素的 value 属性。这样,React 只执行最少的必要操作来使 DOM 元素与最新的 JSX。 如您所知,到目前为止我们一直在讨论受控输入。
让我们以不受控制的输入为例。下面的代码显示了相同的内容。
在这里,即使组件每 5 秒重新渲染一次,运行时所做的输入仍被保留。请记住,这是不受控制的输入,因此没有相同的状态进行备份。运行时的输入仍然被保留。它澄清了 React 不会在每次渲染时触及输入元素。
App.js
import { useState, useEffect } from 'react';
export default function App() {
const [autoRender, setAutoRender] = useState();
useEffect(() => {
const timer = setInterval(() => {
setAutoRender(Math.random());
}, 5000);
return () => clearInterval(timer);
}, []);
return (
<>
<h3>A component auto-renders in 5 seconds</h3>
<label>
An uncontrolled input still retains your input on every render
</label>
<input />
<br />
<br />
<i>The latest state : {autoRender}</i>
</>
);
}