[英]ReactJS: Is it possible to include a parent component in its child component?
我有一个组件,其中包含 ReactJS 中的另一个组件,如下所示:
var Child = require('Child');
var Parent = React.createClass({
render: function() {
return (
<div>
<Child key={someKey} data={someData} />
</div>
);
},
});
module.exports = Parent;
然后在我的子组件中,我想再次包含父组件和子组件。 有点像在彼此嵌套 div。
下面子组件的代码:
var Parent = require('Parent');
var Child = React.createClass({
render: function() {
return (
<div>
<Parent key={someOtherKey} data={someOtherData} />
</div>
);
}
});
module.exports = Child;
虽然我收到以下错误: Uncaught TypeError: e.toUpperCase is not a function
React 中允许这种行为吗? 如果不是,它应该如何构建?
首先,您的代码中存在循环依赖关系, Parent
和Child
都需要彼此。
为了在需要模块时避免无限循环,CommonJS 模块的行为如下:
Parent.js
需要Child.js
,当Child
组件调用require('Parent')
, Parent.js
的导出值是一个空对象。 所以你得到错误e.toUpperCase is not a function
因为e
( Parent
) 是一个空对象。
您应该在module.exports
语句之后要求:
var Parent = React.createClass({
render: function() {
return (
<div>
<Child key={someKey} data={someData} />
</div>
);
},
});
module.exports = Parent;
var Child = require('Child');
但是如果这解决了循环依赖,我不明白你想要实现什么,它实际上是一个无限循环。
这是一个以 getTreeNode 作为共享元素的递归模式。
import React, {Component} from 'react';
import lodash from 'lodash';
var TreeRootSty = {lineHeight: '120%'}
var liSty = {listStyleType: 'none'};
var ulSty = {height: 'inherit', WebkitPaddingStart: '16px'};
var ulStyle = {height: 'inherit', WebkitPaddingStart: '16px'};
var iconSty = {marginRight: '10px', width: '16px'};
var titleSty = {color: '#afac87', marginTop: '2px'};
var nottogglable = {
color: '#FFF',
cursor: 'pointer',
margin: '0 0 0 .8em'
};
var togglable = {
color: '#815C7C',
cursor: 'pointer',
margin: '0'
};
var options = {};
var getTreeNode = function(child, index) {
return <li key={index} style={liSty}><JTreeViewNode node={child} iconClick={this.props.iconClick} titleClick={this.props.titleClick} /></li>;
};
class JTreeViewNodeRender extends Component {
binder(...methods) { methods.forEach( (method) => this[method] = this[method].bind(this) ); }
render() {
var childNodes;
var pSty = nottogglable;
if (lodash.has(this.props.node, 'children') && this.props.node.children.length > 0) {
childNodes = this.props.node.children.map(getTreeNode, this);
titleSty.color = this.props.node.selected ? '#7BB53B' : '#AF90A5';
} else {
titleSty.color = this.props.node.selected ? '#b58900' : '#afac87';
}
var isClosed = true;
if (lodash.has(this.props.node, 'closed')) isClosed = this.props.node.closed;
ulStyle.display = isClosed ? 'none' : 'inline-block';
var props = this.props;
var iconType = lodash.get(props, options.typeName);
if (iconType == options.icon.sun) iconSty.background = "url('./img/sun.ico') 0/16px no-repeat !important";
else if (iconType == options.icon.leaf) iconSty.background = "url('./img/leaf.ico') 0/16px no-repeat !important";
else if (iconType == options.icon.snow) iconSty.background = "url('./img/snow.ico') 0/16px no-repeat !important";
else iconSty.background = "url('./img/sun.ico') 0/16px no-repeat !important";
return (
<div id='TreeNode'>
<div id='pSty' style={pSty} className='FlexBox'>
<div id='iconSty' onClick={this.iconHandler} style={iconSty}> </div>
<div id='titleSty' onClick={this.clickHandler} style={titleSty} >{this.props.node.title}</div>
</div>
<ul id='ulStyle' style={ulStyle}>
{childNodes}
</ul>
</div>
);
}
}
class JTreeViewNode extends JTreeViewNodeRender {
constructor() {
super();
this.binder('clickHandler', 'iconHandler');
}
iconHandler() {
if (lodash.has(this.props.node, 'children') && this.props.node.children.length > 0) {
this.props.iconClick(this.props.node);
} else {
this.clickHandler();
}
}
clickHandler() { this.props.titleClick(this.props.node); }
}
class JTreeViewRender extends Component {
render() {
options = this.props.options;
var childNodes = this.props.data.map(getTreeNode, this);
return (
<div id='TreeRootSty' style={TreeRootSty}>
<ul id='ulSty' style={ulSty}>
{childNodes}
</ul>
</div>
);
}
}
export default class JTreeView extends JTreeViewRender {}
您想要做的没问题,但您必须注意不要创建无限递归,因此您需要一个停止条件。
这是一个JsFiddle可执行示例
function getOffset(depth) {
var prefix = "";
for (var i=0;i<depth;i++) {
prefix = prefix + "-";
}
return prefix;
}
var Parent = React.createClass({
render: function() {
var offset = getOffset(this.props.depth);
return <div>{offset}Parent=[<Child depth={this.props.depth}/>{offset}]</div>;
}
});
var Child = React.createClass({
render: function() {
if ( this.props.depth >= 5 ) {
return false;
}
var newDepth = this.props.depth +1;
var offset = getOffset(this.props.depth);
return <div>{offset}Child=(<Parent depth={newDepth}/>{offset})</div>;
}
});
React.render(<Parent depth={0} />, document.body);
输出是
Parent=[
Child=(
-Parent=[
-Child=(
--Parent=[
--Child=(
---Parent=[
---Child=(
----Parent=[
----Child=(
-----Parent=[-----]
----)
----]
---)
---]
--)
--]
-)
-]
)
]
这很好笑 :)
第一个问题是您不能将两个模块相互导入。 第二个问题是你需要检查是否创建第二个父对象,否则你会得到无限循环。 像这样的东西:
var Child = require('Child');
var Parent = React.createClass({
render: function() {
return (
<div>
<Child key={someKey} data={someData} />
</div>
);
},
});
module.exports = Parent;
进而:
var Child = React.createClass({
render: function() {
var parent = nil;
if ({hasNestedParent}) {
var Parent = require('Parent');
parent = (
<Parent key={someOtherKey} data={someOtherData} />
);
}
return (
<div>{parent}</div>
);
}
});
module.exports = Child;
请注意,除非需要,否则不会在子模块中导入Parent
模块。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.