use*_*782 4 javascript jquery ecmascript-6 reactjs
我正在浏览Integrated-with-jquery-chosen-plugin的react文档文章,react给出了Chosen jquery插件的示例并提到了以下内容:
\n\n\n注意我们如何包裹
\n<select>一个额外的<div>.<select>这是必要的,因为 Chosen 会在我们传递给它的节点后面附加另一个 DOM 元素。然而,就 React 而言,<div>始终只有一个孩子。这就是我们如何确保 React 更新不会与 Chosen 附加的额外 DOM 节点发生冲突。重要的是,如果您在 React 流程之外修改 DOM,则必须确保 React 没有理由触及这些 DOM 节点。
class Chosen extends React.Component {\n render() {\n return (\n <div> \n <select className="Chosen-select" ref={el => this.el = el}> \n {this.props.children}\n </select>\n </div>\n );\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n我最初认为,当<App>使用新setState()调用进行反应重新渲染时,如果我们没有额外的div内容,select那么比较算法就会遇到麻烦,并且dom后面附加的元素select将被删除。但是,显然这并不是正在发生的事情。从代码来看:
<App> | |<App> \n <Component1/> | | <Component1/> \n <Chosen/> | -- rerender --> | <Chosen/> //gets updated and removes nodes after <select>\n <Component2/> | | <Component2/> \n</App> | |</App> \nRun Code Online (Sandbox Code Playgroud)\n我尝试模仿这种情况,令我惊讶的是,即使我不包装select在 a 中div,它也不会更新,并且在select保持不变后添加额外的 dom 节点:
class Chosen extends React.Component {\n render() {\n return (\n <div> \n <select className="Chosen-select" ref={el => this.el = el}> \n {this.props.children}\n </select>\n </div>\n );\n }\n}\nRun Code Online (Sandbox Code Playgroud)\r\n<App> | |<App> \n <Component1/> | | <Component1/> \n <Chosen/> | -- rerender --> | <Chosen/> //gets updated and removes nodes after <select>\n <Component2/> | | <Component2/> \n</App> | |</App> \nRun Code Online (Sandbox Code Playgroud)\r\n2.5 秒后,我添加了一个红色inputdom 节点select,5 秒后,我重新渲染整个应用程序。现在为什么不通过重新渲染反应比较算法删除红色input?select如果我把它包裹在一个额外的东西里会有什么不同div?基本上我正在寻找引用的反应文档的解释。
这很可能不是一个完整的答案,但太长,无法作为评论发布。
在这种特定情况下,您定义一个名为 Chosen 的 React 组件:
class Chosen extends React.Component {
render() {
return (
<div>
<select className="Chosen-select" ref={el => this.el = el}>
{this.props.children}
</select>
</div>
);
}
}
Run Code Online (Sandbox Code Playgroud)
在 React 中,一个组件永远不能返回多个“顶级”元素,因为它没有任何意义。
所以一个更简单的组件是这样的:
class Chosen extends React.Component {
render() {
return (
<div>
</div>
<div>
</div>
);
}
}
Run Code Online (Sandbox Code Playgroud)
是“非法的”,因为组件必须始终只返回一个“顶级”元素。如果出于某种原因您希望组件返回多个元素(如上例所示),则必须将它们包装到 div 中:
class Chosen extends React.Component {
render() {
return (
<div>
<div>
</div>
<div>
</div>
<div>
);
}
}
Run Code Online (Sandbox Code Playgroud)
现在您将正确地仅返回一个顶级元素,然后该元素又将这两个 div 作为子元素。
因此,在您的情况下,如果您要这样做:
class Chosen extends React.Component {
render() {
return (
<select className="Chosen-select" ref={el => this.el = el}>
{this.props.children}
</select>
);
}
}
Run Code Online (Sandbox Code Playgroud)
它不会工作(即使它看起来只有一个元素),因为所选的库显然是这样工作的,因此它将将该选择组件变成这样的东西,例如:
class Chosen extends React.Component {
render() {
return (
<div class = "chosen-select-label">My select</div>
<div class = "chosen-select">
<select>
<option></option>
<option></option>
</select>
</div>
<div class = "some-other-chosen-select-shenanigans">
...
</div>
);
}
}
Run Code Online (Sandbox Code Playgroud)
现在 React 遇到了一个问题,因为组件返回多个元素。但是,如果将 select 包装到 div 中,结果将如下所示:
class Chosen extends React.Component {
render() {
return (
<div>
<div class = "chosen-select-label">My select</div>
<div class = "chosen-select">
<select>
<option></option>
<option></option>
</select>
</div>
<div class = "some-other-chosen-select-shenanigans">
...
</div>
</div>
);
}
}
Run Code Online (Sandbox Code Playgroud)
React 会再次高兴起来。
据我所知,这种 div 包装方法是一种相当古老的方法。更现代的方法是使用React Fragments。
至于为什么会存在这样的规则,我一直认为它与 JavaScript 的普通函数类似,所以这样的事情没有任何意义:
function func() {
return 1;
return 2;
}
Run Code Online (Sandbox Code Playgroud)
如果我们真的想返回 1 和 2,我们会将它们包装成数组之类的东西:
function func() {
return [1, 2];
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
277 次 |
| 最近记录: |