如何有效地切换多个元素的 CSS 属性



我的工作解决方案如下。 但它不能很好地扩展并且看起来很冗长。

我希望能够在不创建太多代码的情况下添加越来越多的<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>

最新更新