마켓컬리 nav 작업

나는 마켓컬리에서 nav제품상세 페이지를 맡았다. 우선 가장 금방 끝낼 수 있을 것 같은 nav를 먼저 만들었지만 hover에서 hover가 되는 것을 구현하는게 생각보다 오래걸렸다.
개발시간을 잡을때 내가 생각하는 시간의 x2를 해야한다는게 맞는 말인 것 같다. 😭

hover에 hover를 어떻게 구현해야할까??

우선 카테고리를 hover하게 되면 리스트 목록이 나오고 목록의 list에 hover를 하게되면 한 번더 슬라이드가 되서 조금 더 자세한 목록들이 출력이 된다.

일단 목록에서 슬라이드된 메뉴를 보여주기 위해서는 슬라이드된 메뉴를 absoulte로 고정하고 left:200px 값을 줬다.
그리고 hover리스트를 감싸고 있는 큰 부모박스의 스타일로 width: 220px, overflow:hidden을 주고 전체 카테고리에 hover 됐을 때 width:450px을 늘려주면 마치 슬라이드되서 나오는 것처럼 보이게 할 수 있다.

여기서 핵심
예를 들어 햄버거에 호버를하고 슬라이드된 메뉴에 마우스를 over할때 햄버거 목록이 계속 선택이 되어있는 것 처럼 구현해야한다.

<div className="menu-hover-box" style={allCategoriesHover ? { display: 'flex', width: `${hoverWidth}px` } : { display: 'none' }} onMouseLeave={this.allCategoriesHoverLeave}>
  <div className="menu-hover">
    <ul className="menu-hover-list">
      {navbarList.map((list, index) => (
        <NavBarHoverList displayShowIndex={displayShowIndex} list={list} index={index + 1} key={index} categoriesMenuHoverEnter={this.categoriesMenuHoverEnter} />
      ))}
    </ul>
  </div>
</div>

navbarListmap()으로 각각의 list<NavBarHoberList>로 전달하는데 index값을 전달한다. index+1하는 이유는 mock data의 id값이 1부터 시작하기 때문

displayShowIndex는 몇 번째의 목록 슬라이드 메뉴를 보여줄 것인지를 알기 위해 자식 인 <NavBarHoverList> 컴포넌트로 보낸다. 그리고 목록을 hover하면 몇 번째 인덱스를 hover 했는지 전달하면 현재 어디를 hover하고 있는지를 알 수 있다.

mosueOnLinkEnter = e => {
    this.props.categoriesMenuHoverEnter(e.target.id);
  };

  render() {
    const { displayShowIndex, index, list } = this.props;
    return (
      <li>
        <Link to="#" id={index} className={'menu-hover-list-name ' + (parseInt(displayShowIndex) === list.navbarId ? 'hover-on' : null)} onMouseEnter={this.mosueOnLinkEnter}>
          <span>&nbsp;{list.categoriesMenuName}</span>
        </Link>
        {parseInt(displayShowIndex) === index && (
          <ul className="menu-sub-list">
            {list.categoriesSubMenuName.map((list, index) => (
              <li key={index}>
                <Link to="#" className="sub-list-link">
                  <span className="sub-list-name">{list}</span>
                </Link>
              </li>
            ))}
          </ul>
        )}
      </li>
    );
  }

구현한 코드 (간략히)

// Nav Component
<ul className="menu-main-list">
  <li className="menu1" onMouseEnter={this.allCategoriesHoverEnter}>
    <Link to="#" className="menu1-link">
      <FiMenu className="menu1-icon" />
      <span className="menu-text">전체 카테고리</span>
    </Link>
  </li>
  ...
  ...
<div className="menu-hover-box" style={allCategoriesHover ? { display: 'flex', width: `${hoverWidth}px` } : { display: 'none' }} onMouseLeave={this.allCategoriesHoverLeave}>
  <div className="menu-hover">
  <ul className="menu-hover-list">
    {navbarList.map((list, index) => (
      <NavBarHoverList displayShowIndex={displayShowIndex} list={list} index={index + 1} key={index} categoriesMenuHoverEnter={this.categoriesMenuHoverEnter} />
    ))}
  </ul>
  </div>
</div>

// NavBarHoverList component
class NavBarHoverList extends React.Component {
  mosueOnLinkEnter = e => {
    this.props.categoriesMenuHoverEnter(e.target.id);
  };

  render() {
    const { displayShowIndex, index, list } = this.props;
    return (
      <li>
        <Link to="#" id={index} className={'menu-hover-list-name ' + (parseInt(displayShowIndex) === list.navbarId ? 'hover-on' : null)} onMouseEnter={this.mosueOnLinkEnter}>
          <span>&nbsp;{list.categoriesMenuName}</span>
        </Link>
        {parseInt(displayShowIndex) === index && (
          <ul className="menu-sub-list">
            {list.categoriesSubMenuName.map((list, index) => (
              <li key={index}>
                <Link to="#" className="sub-list-link">
                  <span className="sub-list-name">{list}</span>
                </Link>
              </li>
            ))}
          </ul>
        )}
      </li>
    );
  }
}

메뉴 카테고리에서 onMouseEnter 이벤트가 발생하면 allCategoriesHoverEnter

allCategoriesHoverEnter = () => {
    this.setState({
      allCategoriesHover: true,
      hoverWidth: this.HOVER_WIDTH_TYPE1,
    });
  };

allCategoriesHover: true값을 주게 되면 hover 카테고리가 display: flex로 바뀌게 되고 목록 리스트가 출력이 된다.
hoverWidth: this.HOVER_WIDTH_TYPE1(220) : hover에 관련된 최상위 부모 width값을 220으로 수정

0개의 댓글