React as a UI Runtime(四、条件)
正如下面的代碼,假如我們開始至需要一個(gè)input,但稍后需要在它之前渲染一個(gè)message : // 第一次渲染 ReactDOM.render(<dialog><input /></dialog>,domContainer );// 第二次渲染 ReactDOM.render(<dialog><p>I was just added here!</p><input /></dialog>,domContainer );
在這個(gè)例子中,<input>宿主實(shí)例將會(huì)被重建。React會(huì)遍歷元素樹,并與之前的版本比較:
- dialog → dialog: 可以重復(fù)使用嗎? 可以-type匹配。
- input → p:可以重復(fù)使用嗎?不行,type已經(jīng)改變了!需要?jiǎng)h除存在的input,并創(chuàng)建新的p宿主實(shí)例。
- (nothing) → input: 需要新建一個(gè)input宿主實(shí)例。
React這樣的代碼是如下的:
let oldInputNode = dialogNode.firstChild; dialogNode.removeChild(oldInputNode);let pNode = document.createElement('p'); pNode.textContent = 'I was just added here!'; dialogNode.appendChild(pNode);let newInputNode = document.createElement('input'); dialogNode.appendChild(newInputNode);這不是一種好的更新方式,因?yàn)樵瓌t上input并沒有被p替代-它僅僅是移動(dòng)了。我們不想要因?yàn)橹匦聞?chuàng)建Dom元素而失去它的選中狀態(tài),聚焦?fàn)顟B(tài)和顯示內(nèi)容。
幸好這個(gè)問題有一個(gè)簡單的修復(fù)方式,他并不在React應(yīng)用中常見。
在實(shí)踐中,你很少會(huì)直接調(diào)用ReactDOM.render,實(shí)際上,React app常常會(huì)拆分成像下面這樣的函數(shù):
This example doesn’t suffer from the problem we just described. It might be easier to see why if we use object notation instead of JSX. Look at the dialog child element tree:
這個(gè)例子并不會(huì)有我們之前描述的那個(gè)問題,如果我們使用對(duì)象來代替JSX描述會(huì)更加明顯,下面是dialog子元素樹:
function Form({ showMessage }) {
let message = null;
if (showMessage) {
}
return {
};
}
不管showMessage 是true的還是false,<input>是第二個(gè)子元素,并且在render中不會(huì)改變它的位置。
如果showMessage 從false變?yōu)閠rue,React會(huì)遍歷元素樹,并與之前的版本相比較:
- dialog → dialog:可以重復(fù)使用嗎? 可以-type匹配。
- (null) → p:需要插入一個(gè)新的p宿主實(shí)例。
- input → input: 可以重復(fù)使用嗎? 可以-type匹配。
那么React會(huì)執(zhí)行類似于下面的代碼:
let inputNode = dialogNode.firstChild; let pNode = document.createElement('p'); pNode.textContent = 'I was just added here!'; dialogNode.insertBefore(pNode, inputNode);input的狀態(tài)并不會(huì)改變
總結(jié)
以上是生活随笔為你收集整理的React as a UI Runtime(四、条件)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 脑洞大开的翻转代码
- 下一篇: 虚拟机VMware12下安装window