如果React在更新中只重用与元素范例相婚配的宿主实例,那按衬着前提挑选的内容怎么办呢?
正以下面的代码,如果我们最先至须要一个
input
,但稍后须要在它之前衬着一个
message
:
// 第一次衬着
ReactDOM.render(
<dialog>
<input />
</dialog>,
domContainer
);
// 第二次衬着
ReactDOM.render(
<dialog>
<p>I was just added here!</p>
<input />
</dialog>,
domContainer
);
在这个例子中,<input>
宿主实例将会被重修。React会遍历元素树,并与之前的版本比较:
- dialog → dialog: 能够重复运用吗? 能够-type婚配。
- input → p:能够重复运用吗?不可,type已转变了!须要删除存在的
input
,并建立新的p
宿主实例。 - (nothing) → input: 须要新建一个input宿主实例。
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);
这不是一种好的更新体式格局,由于原则上input
并没有被p
替换-它仅仅是移动了。我们不想要由于重新建立Dom元素而落空它的选中状况,聚焦状况和显现内容。
幸亏这个题目有一个简朴的修复体式格局,他并不在React运用中常见。
在实践中,你很少会直接挪用ReactDOM.render
,实际上,React app常常会拆分成像下面如许的函数:
function Form({ showMessage }) {
let message = null;
if (showMessage) {
message = <p>I was just added here!</p>;
}
return (
<dialog>
{message}
<input />
</dialog>
);
}
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:
这个例子并不会有我们之前形貌的那个题目,如果我们运用对象来替代JSX形貌会越发显著,下面是dialog子元素树:
function Form({ showMessage }) {
let message = null;
if (showMessage) {
message = {
type: 'p',
props: { children: 'I was just added here!' }
};
}
return {
type: 'dialog',
props: {
children: [
message,
{ type: 'input', props: {} }
]
}
};
}
function Form({ showMessage }) {
let message = null;
if (showMessage) {
message = {
type: 'p',
props: { children: 'I was just added here!' }
};
}
return {
type: 'dialog',
props: {
children: [
message,
{ type: 'input', props: {} }
]
}
};
}
不论showMessage 是true的照样false,<input>
是第二个子元素,并且在render中不会转变它的位置。
如果showMessage 从false变成true,React会遍历元素树,并与之前的版本相比较:
- dialog → dialog:能够重复运用吗? 能够-type婚配。
- (null) → p:须要插进去一个新的p宿主实例。
- input → input: 能够重复运用吗? 能够-type婚配。
那末React会实行类似于下面的代码:
let inputNode = dialogNode.firstChild;
let pNode = document.createElement('p');
pNode.textContent = 'I was just added here!';
dialogNode.insertBefore(pNode, inputNode);
input的状况并不会转变