javascript 单击 react.js 时切换列表的背景颜色
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/31413023/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Toggle background color of list on click react.js
提问by Vamshi Kolanu
I am trying to create a list which has following features.
我正在尝试创建一个具有以下功能的列表。
- On hover change background color of the listItem.
- On Click change background color of a listItem.
- Toggle background color between clicked elements.[i.e. Only one element in the list can have clicked property]
- 在悬停时更改 listItem 的背景颜色。
- 单击更改列表项的背景颜色。
- 在单击的元素之间切换背景颜色。[即列表中只有一个元素可以具有单击属性]
I have executed onhover 1 and 2 features, but I am not able to implement the 3rd feature. Please help me to solve this problem.
我已经执行了 onhover 1 和 2 功能,但我无法实现第三个功能。请帮我解决这个问题。
Thanks in advance.
提前致谢。
/** @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>
)
}
});
回答by FariaC
Before looking at any code, think about the actual cause of the problem. In your current implementation, each ListItem maintains its own click_flag state. When one ListItem is clicked, it sets its own click_flag to true, but this does not trigger the other ListItems to reset their own click_flag to false. This is the cause of the problem. The solution is to pass the click_flag as a props from the parent to each ListItem. It is the parent's responsibility to ensure that only ListItem gets prop as true, while the others are false. Likewise, it is the ListItem's responsibility to notify the parent when it has been clicked via a callback props passed down from the parent.
在查看任何代码之前,请考虑问题的实际原因。在您当前的实现中,每个 ListItem 都维护自己的 click_flag 状态。单击一个 ListItem 时,它会将自己的 click_flag 设置为 true,但这不会触发其他 ListItem 将它们自己的 click_flag 重置为 false。这就是问题的原因。解决方案是将 click_flag 作为道具从父级传递给每个 ListItem。父母有责任确保只有 ListItem 的 prop 为真,而其他的为假。同样,当 ListItem 通过从父级传递过来的回调道具被点击时通知父级是 ListItem 的责任。
So, the ListItem looks like:
所以,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>
);
}
});
And, the parent could look like this:
而且,父对象可能如下所示:
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>
);
}
});
The parent maintains the state variable which stores which ListItem is the current selected one. It uses this state in render() to pass is_selected = true to only one ListItem, and all the others are passed false. The parent's state is updated by the clickHandler which is passed down as a props to each ListItem. See example fiddle here
父级维护状态变量,该变量存储哪个 ListItem 是当前选定的项。它在 render() 中使用此状态仅将 is_selected = true 传递给一个 ListItem,而其他所有传递给 false。父级的状态由作为道具传递给每个 ListItem 的 clickHandler 更新。在这里查看示例小提琴
回答by Dhiraj
Since there will be only one selected item the parent component can maintain a state with the selected item index.
由于只有一个选定项,因此父组件可以使用选定项索引保持状态。
Parent Component
父组件
getInitialState: function(){
return {selectedItem : null, items: this.props.data};
}
Change the render method to something like this (notice the isSelected property that is being sent to the ListItem component)
将渲染方法更改为类似的内容(注意发送到 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
});
Lets implement onSelectHandler later.
让我们稍后实现 onSelectHandler。
ListItem
项目清单
In the definition transfer the prop isSelected to ListItem's state
在定义中将道具 isSelected 转移到 ListItem 的状态
getInitialState: function(){
return {hover_flag: false, click_flag: this.props.isSelected} // <---- notice the change here
}
Now modify the clickEvent and trigger ListItem's onSelect property and send the clicked ListItem's name (i would suggest a unique ID here too)
现在修改 clickEvent 并触发 ListItem 的 onSelect 属性并发送单击的 ListItem 的名称(我也建议在这里使用唯一 ID)
clickEvent: function(){
this.setState({click_flag: true});
this.props.onSelect(this.props.name); // <--- I would suggest sending ID
}
Lets implement onSelectHandler for the parent component now
现在让我们为父组件实现 onSelectHandler
onSelectHandler: function(childItemID){
this.setState({selectedItem: childItemID});
}
Hope this makes sense
希望这是有道理的