我正在制作这个递归列表视图,如果切换父复选框,我试图显示/隐藏子组件。我在这里做错了,我不能再让它工作了。问题似乎与输入标记中onClick()
函数的参数有关。我是React的新手,无法找到解决这个问题的方法。我可以帮忙解决一下这个问题吗?
export default class MyList extends Component {
constructor(props) {
super(props);
this.state = {
visible: true
};
}
toggle = () => {
this.setState(
{visible: !this.state.visible}
);
};
render() {
var style;
if (!this.state.visible) {
style = {display: "none"};
}
var node = this.props.data;
return(
<div>
<ul style={style}>
{
Object.keys(this.props.data).map(function(key){
return (
<li key={key}><input type="checkbox" onClick={MyList.toggle}/>
<label>{key}</label> :
{typeof node[key] === 'object' ? <MyList data = {node[key]} /> : node[key]}
</li>
);
})
}
</ul>
</div>
);
}
}
答案 0 :(得分:1)
我不确定你到底要做什么 正如你在我们的评论中所看到的那样,我试图理解,但我仍然没有得到这个想法 从来没有那么简单,只是为了回答你的问题,并指出你正确的方向,你的问题是这一行:
onClick={MyList.toggle}
toggle
是一种属于类的实例的方法,它不是静态成员,因此您必须在实例的上下文中调用它。 />
diong的一种方法是使用this
作为当前实例的引用。问题是您在.map
的{{1}}内使用匿名函数,Object.keys
不再引用该实例。
为了确保this
是类实例的引用,您可以使用箭头函数,该函数使用this
的词汇上下文。
this
或者做旧的和丑陋的风格&#34;在函数的顶行使用{Object.keys(this.props.data).map(key => {
return (
<li key={key}>
<input type="checkbox" onClick={this.toggle} />
...
。 (我更喜欢第二种选择)
顺便说一句,您将var that = this
对象放在style
元素上,这意味着一次点击后将隐藏整个ul
。不确定这是你的意图。
以下是您的代码的运行示例:
ul
&#13;
class MyList extends React.Component {
constructor(props) {
super(props);
this.state = {
visible: true
};
}
toggle = () => {
this.setState({ visible: !this.state.visible });
};
render() {
var style;
if (!this.state.visible) {
style = { display: "none" };
}
var node = this.props.data;
return (
<div>
<ul style={style}>
{Object.keys(this.props.data).map(key => {
return (
<li key={key}>
<input type="checkbox" onClick={this.toggle} />
<label>{key}</label> :
{typeof node[key] === "object" ? (
<MyList data={node[key]} />
) : (
node[key]
)}
</li>
);
})}
</ul>
</div>
);
}
}
ReactDOM.render(<MyList data={[1, 2, 3]} />, document.getElementById("root"));
&#13;
修改强>
作为评论的后续内容:
尝试制作类似this Fiddle的内容,而不是 复选框,但我无法折叠列表。
以下是带有复选框输入的链接中的代码版本:
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>
&#13;
class TreeNode extends React.Component {
constructor(props) {
super(props);
this.state = {
visible: true
};
}
toggle = () => {
this.setState({ visible: !this.state.visible });
};
render() {
var childNodes;
var classObj;
if (this.props.node.childNodes != null) {
childNodes = this.props.node.childNodes.map(function(node, index) {
return (
<li key={index}>
<TreeNode node={node} />
</li>
);
});
classObj = {
togglable: true,
"togglable-down": this.state.visible,
"togglable-up": !this.state.visible
};
}
var style;
if (!this.state.visible) {
style = { display: "none" };
}
return (
<div>
<h5 className={classNames(classObj)}>
<input
checked={this.state.visible}
type="checkbox"
onClick={this.toggle}
/>
{this.props.node.title}
</h5>
<ul style={style}>{childNodes}</ul>
</div>
);
}
}
var tree = {
title: "howdy",
childNodes: [
{ title: "bobby" },
{
title: "suzie",
childNodes: [
{
title: "puppy",
childNodes: [{ title: "dog house" }]
},
{ title: "cherry tree" }
]
}
]
};
ReactDOM.render(<TreeNode node={tree} />, document.getElementById("root"));
&#13;
body {
font-family: "Helvetica Neue";
}
h3 {
color: #BF616A;
}
.togglable {
color: #D78770;
cursor: pointer;
}
.togglable-down::after,
.togglable-up::after {
font-size: 8px;
margin-left: 0.5em;
}
.togglable-down::after {
content: "▼";
display: inline-block;
}
.togglable-up::after {
content: "▶";
display: inline-block;
}
&#13;