我正在尝试创建一个具有以下功能的列表。
我已经执行了onhover 1和2功能,但我无法实现第3个功能。请帮我解决这个问题。
提前致谢。
/** @jsx React.DOM */
'use strict'
var React = require('react')
var ListItem = React.createClass({
getInitialState: function() {
return {hover_flag: false, click_flag: false}
},
hoverEvent: function() {
this.setState({hover_flag: !this.state.hover_flag})
},
clickEvent: function(){
this.setState({click_flag: true})
},
render: function() {
var liStyle = {
/* some more class properties */
background: '#cc181e',
}
if(this.state.hover_flag || this.state.click_flag) {
liStyle['background'] = '#880000'
}
if(this.state.click_flag) {
liStyle['background'] = '#880000'
}
return (
<li onClick={this.clickEvent} onMouseEnter={this.hoverEvent} onMouseLeave={this.hoverEvent} style={liStyle} key={this.props.name}>{this.props.name}</li>
)
}
})
module.exports = React.createClass({
render: function() {
var ulStyle = {
padding: '0px',
margin: '20px',
}
var link = {
textDecoration: 'none',
color: 'white',
cursor: 'pointer'
}
var list = this.props.data.map(function(data) {
/*List of li elements */
return <ListItem name={data.name} />
})
return (
<ul style={ulStyle}>
{list}
</ul>
)
}
});
答案 0 :(得分:6)
在查看任何代码之前,请考虑问题的实际原因。在当前的实现中,每个ListItem都维护自己的click_flag状态。单击一个ListItem时,它会将自己的click_flag设置为true,但这不会触发其他ListItem将其自己的click_flag重置为false。这是问题的原因。解决方案是将click_flag作为道具从父项传递给每个ListItem。父母有责任确保只有ListItem才能将prop视为true,而其他则为false。同样,ListItem负责通过从父代传下来的回调道具点击它时通知父母。
因此,ListItem看起来像:
var ListItem = React.createClass({
propTypes: {
onClick: React.PropTypes.func.isRequired,
isSelected: React.PropTypes.bool
},
getDefaultProps: function() {
return {
isSelected: false
};
},
getInitialState: function() {
return {
hover_flag: false
};
},
hoverEvent: function() {
this.setState({hover_flag: !this.state.hover_flag});
},
render: function() {
var liStyle = {
background: '#cc181e'
};
if (this.props.isSelected || this.state.hover_flag) {
liStyle['background'] = '#880000';
}
return (
<li
onClick={this.props.onClick}
onMouseEnter={this.hoverEvent}
onMouseLeave={this.hoverEvent}
style={liStyle}>{this.props.name}
</li>
);
}
});
并且,父母可能看起来像这样:
module.exports = React.createClass({
getInitialState: function() {
return {
selectedItem: null
};
},
clickHandler: function(idx) {
this.setState({selectedItem: idx});
},
render: function() {
var ulStyle = {
padding: '0px',
margin: '20px'
};
var items = this.props.data.map(function (item, idx) {
var is_selected = this.state.selectedItem == idx;
return <ListItem
key={item.name}
name={item.name}
onClick={this.clickHandler.bind(this, idx)}
isSelected={is_selected}
/>;
}.bind(this));
return (
<ul style={ulStyle}>
{items}
</ul>
);
}
});
父级维护状态变量,该变量存储哪个ListItem是当前选定的ListItem。它在render()中使用此状态将is_selected = true传递给一个ListItem,并将所有其他传递给false。父对象的状态由clickHandler更新,clickHandler作为props传递给每个ListItem。见example fiddle here
答案 1 :(得分:1)
由于只有一个选定的项目,父组件可以维持具有所选项目索引的状态。
父组件
getInitialState: function(){
return {selectedItem : null, items: this.props.data};
}
将render方法更改为类似的方法(注意发送给ListItem组件的isSelected属性)
var selectedItem = this.state.selectedItem;
var list = this.state.items.map(function(data) {
/*List of li elements */
return <ListItem name={data.name} onSelect={this.onSelectHandler} isSelected={selectedItem === data.id} key={data.id}/> // <--- I would suggest having a unique ID
});
让我们稍后实现onSelectHandler。
<强>列表项强>
在定义转移中,prop被选择为ListItem的状态
getInitialState: function(){
return {hover_flag: false, click_flag: this.props.isSelected} // <---- notice the change here
}
现在修改clickEvent并触发ListItem的onSelect属性并发送单击的ListItem的名称(我也建议在这里使用一个唯一的ID)
clickEvent: function(){
this.setState({click_flag: true});
this.props.onSelect(this.props.name); // <--- I would suggest sending ID
}
让我们为父组件实现onSelectHandler
onSelectHandler: function(childItemID){
this.setState({selectedItem: childItemID});
}
希望这是有道理的