我的工作解决方案如下。 但它不能很好地扩展并且看起来很冗长。
我希望能够在不创建太多代码的情况下添加越来越多的<li>
标签。
此代码只是切换下边框,以便您知道选择了什么。
render () {
var style_fave;
var style_splash;
if (this.props.state.current === 'splash') {
style_splash = {
borderBottom: '3px solid #000000'
};
style_fave = {
borderBottom: ''
};
}
if (this.props.state.current === 'fave') {
style_fave = {
borderBottom: '3px solid #000000'
};
style_splash = {
borderBottom: ''
};
}
return (
// ... snip
<li style={style_fave} id="mm_top_list_item" onClick={this.clickHandler2.bind(this)}>
<span className="menu_item">
<img className = 'item_svg' src="_images/sv_star_5_custom.svg"/>
</span>
</li>
<li style={style_splash} onClick={this.clickHandler3.bind(this)} id="nav_splash">
<span id="nav_splash_inner" className="menu_item">SIGNON</span>
</li>
// ... snip
尝试这样的代码,它实际上只是将共性提取到顶部
// outside your class definition
const liStyle = {};
const selectedLiStyle = {...liStyle, borderBottom: "3px solid black" };
// snip
render() {
const c = this.props.state.current;
return (
// snip
<li style={c==="fave" ? selectedLiStyle : liStyle } ... />
<li style={c==="splash" ? selectedLiStyle : liStyle } ... />
...
);
}
您希望尽可能多地分离关注点。这是我在评论中试图表达的内容的人为示例:
// something from state
const navItemState = [{
name: 'Questions',
active: false,
}, {
name: 'Posts',
active: true,
}, {
name: 'Jobs',
active: false
}]
// nav item that encapsulates its own logic and style based on state
const NavItem = ({active, name}) => (
<li style={active ? {borderBottom: '1px solid orange'} : {}}>{name}</li>
)
// map over nav items to generate a nav
const Nav = () => (
<ul>
{navItemState.map(item => (
<NavItem active={item.active} name={item.name} />
))}
</ul>
)
ReactDOM.render(
<Nav />,
document.getElementById('app')
);
<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="app"></div>
基本上,您将列表项元数据存储在某个地方 - 可能是外部状态存储,可能是组件状态,可能基于路由(我不确定您的应用程序设置)。重要的一点是,您希望每个组件都进行自我管理。与其使用一个巨大的渲染函数来硬编码每个列表项,然后确定每个列表项中应该包含的样式,不如尝试尽可能多地泛化,以便您有一个像"活动"这样的概念。如果每个列表项只能占据两个状态,则您正在查看单个布尔值来控制每个状态。将所有常用逻辑抽象到NavItem
组件中后,您可以简单地将一个 prop 传递给每个 prop,而不必担心每次要添加新列表项时都传递带有逻辑的整个样式对象。
一种更"反应"的方法是让 a 组件管理当前选择菜单项的状态。然后,它作为道具向动到菜单项,并确定如何更新其演示文稿。
单击菜单项时,它位于 onClick 调用父项 MenuClicked 函数来设置新状态,菜单项可以根据需要自行更新。
状态和道具是反应如何工作的基础,也是一开始要理解的最重要的东西。
注意:如果您正在或决定使用 react-router 来管理路由,它有一个内置的 NavLink 组件,可以轻松设置导航栏和链接的样式。
class App extends React.Component {
constructor (props){
super(props)
this.state = {
activeMenuItem: ''
}
}
menuClicked(e) {
this.setState({activeMenuItem: e.target.innerHTML})
}
isActive(item) {
return item === this.state.activeMenuItem
}
render() {
return (
<div>
<Menu>
<MenuItem label="Home" activeItem={this.isActive("Home")} onClick={(e) => this.menuClicked(e)} />
<MenuItem label="Details" activeItem={this.isActive("Details")} onClick={(e) => this.menuClicked(e)} />
<MenuItem label="About" activeItem={this.isActive("About")} onClick={(e) => this.menuClicked(e)} />
</Menu>
</div>
);
}
}
const MenuItem = props => {
let styles = {
listStyle: "none",
display: "inline-flex",
alignItems: "center",
padding: "0 10px"
}
if (props.activeItem) {
styles = {...styles, borderBottom: "3px solid darkgray"}
}
return (
<li
style={styles}
onClick={(e) => props.onClick(e)}
>
{props.label}
</li>
);
};
const Menu = props => {
return (
<div
style={{
width: "100%",
height: 75,
backgroundColor: "lightgray",
display: "flex"
}}
>
{props.children}
</div>
);
};
ReactDOM.render(<App />, document.getElementById("root"));
<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>