o01*_*o01 84 javascript reactjs
假设我有一个具有条件渲染的视图组件:
render(){
if (this.state.employed) {
return (
<div>
<MyInput ref="job-title" name="job-title" />
</div>
);
} else {
return (
<div>
<MyInput ref="unemployment-reason" name="unemployment-reason" />
<MyInput ref="unemployment-duration" name="unemployment-duration" />
</div>
);
}
}
Run Code Online (Sandbox Code Playgroud)
MyInput看起来像这样:
class MyInput extends React.Component {
...
render(){
return (
<div>
<input name={this.props.name}
ref="input"
type="text"
value={this.props.value || null}
onBlur={this.handleBlur.bind(this)}
onChange={this.handleTyping.bind(this)} />
</div>
);
}
}
Run Code Online (Sandbox Code Playgroud)
让我们说employed是真的.每当我将其切换为false而另一个视图呈现时,只会unemployment-duration重新初始化.还会unemployment-reason预先填充值job-title(如果在条件更改之前给出了值).
如果我将第二个渲染例程中的标记更改为如下所示:
render(){
if (this.state.employed) {
return (
<div>
<MyInput ref="job-title" name="job-title" />
</div>
);
} else {
return (
<div>
<span>Diff me!</span>
<MyInput ref="unemployment-reason" name="unemployment-reason" />
<MyInput ref="unemployment-duration" name="unemployment-duration" />
</div>
);
}
}
Run Code Online (Sandbox Code Playgroud)
看起来一切正常.看起来React只是没有分散'职称'和'失业原因'.
请告诉我我做错了什么......
Ale*_*x K 153
更改组件的键.
<Component key="1" />
Run Code Online (Sandbox Code Playgroud)
<Component key="2" />
Run Code Online (Sandbox Code Playgroud)
组件将被卸载,并且由于密钥已更改,因此将安装新的Component实例.
Chr*_*ris 90
可能发生的是React认为在渲染之间只添加了一个MyInput(unemployment-duration).因此,job-title永远不会被替换unemployment-reason,这也是交换预定义值的原因.
当React执行diff时,它将根据其key属性确定哪些组件是新组件以及哪些组件是旧组件.如果代码中没有提供这样的密钥,它将生成自己的密钥.
您提供的最后一个代码片段之所以起作用,是因为React基本上需要更改父级下所有元素的层次结构,div我相信这会触发所有子级的重新呈现(这就是它工作的原因).如果你添加span到底部而不是顶部,前面元素的层次结构不会改变,并且那些元素不会重新渲染(问题会持续存在).
以下是官方React文档所说的内容:
当孩子们被洗牌时(如在搜索结果中)或者如果新组件被添加到列表的前面(如在流中),情况变得更加复杂.在这些情况下,必须在渲染过程中保持每个孩子的身份和状态,您可以通过为每个孩子分配一个密钥来唯一地识别每个孩子.
当React协调键控子项时,它将确保任何具有键的子项将被重新排序(而不是被破坏)或被销毁(而不是重用).
您应该能够通过key自己向父元素div或所有MyInput元素提供唯一元素来解决此问题.
例如:
render(){
if (this.state.employed) {
return (
<div key="employed">
<MyInput ref="job-title" name="job-title" />
</div>
);
} else {
return (
<div key="notEmployed">
<MyInput ref="unemployment-reason" name="unemployment-reason" />
<MyInput ref="unemployment-duration" name="unemployment-duration" />
</div>
);
}
}
Run Code Online (Sandbox Code Playgroud)
要么
render(){
if (this.state.employed) {
return (
<div>
<MyInput key="title" ref="job-title" name="job-title" />
</div>
);
} else {
return (
<div>
<MyInput key="reason" ref="unemployment-reason" name="unemployment-reason" />
<MyInput key="duration" ref="unemployment-duration" name="unemployment-duration" />
</div>
);
}
}
Run Code Online (Sandbox Code Playgroud)
现在,当React执行差异时,它会看到它们divs是不同的并将重新呈现它,包括它的所有'子项(第1个示例).在第二个例子中,diff将成功job-title,unemployment-reason因为它们现在有不同的键.
您当然可以使用您想要的任何键,只要它们是唯一的.
2017年8月更新
为了更好地了解密钥在React中的工作方式,我强烈建议您阅读我在React.js中理解唯一密钥的答案.
2017年11月更新
此更新应该在不久前发布,但ref现在不推荐使用字符串文字.例如ref="job-title",现在应该是ref={(el) => this.jobTitleRef = el}(例如).有关详细信息,请参阅我对使用this.refs的弃用警告的回答.
setState在视图中使用以更改employed状态属性.这是React渲染引擎的示例.
someFunctionWhichChangeParamEmployed(isEmployed) {
this.setState({
employed: isEmployed
});
}
getInitialState() {
return {
employed: true
}
},
render(){
if (this.state.employed) {
return (
<div>
<MyInput ref="job-title" name="job-title" />
</div>
);
} else {
return (
<div>
<span>Diff me!</span>
<MyInput ref="unemployment-reason" name="unemployment-reason" />
<MyInput ref="unemployment-duration" name="unemployment-duration" />
</div>
);
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
67887 次 |
| 最近记录: |