0

我使用Carbon 的 SideNav组件作为页面的树形导航控件。叶子可以active通过isActive布尔属性或添加来设置aria-current='page'。如果叶子在子菜单中,则在其任何子菜单处于活动状态时扩展菜单。活动项目跟踪不是开箱即用的,它必须添加。我有两个问题:

  1. 实施活动项目跟踪的正确方法是什么?我可以想到两种方法:onClick()为每个添加一个,SideNavMenuItem或者,正如我目前实现的那样:将一个引用数组放在一起,然后使用useEffect()从所有类中删除活动类并将其添加到选定的类
  2. 当包含组件安装时(例如在页面刷新或通过书签导航到页面)时,标记活动项目的正确方法是什么。我的参考代码通过将所需的类添加到菜单项来设置活动状态,但SideNavMenu只有在其任何子项处于活动状态时才会打开 - 这是我无法通过参考设置的属性。

我当前的示例基于一个小的 8 项树,但我必须将其扩展到更大的规模。

const MySidebar = () => {

  const menuRefs = useRef(new Array());

  useEffect(() => {
    const className = "bx--side-nav__link--current";
    menuRefs.current.forEach(ref => {ref.classList.remove(className)})
    const ref = menuRefs.current.filter((ref) => ref.baseURI === ref.href);
    if (ref) {
      ref[0].classList.add(className);
    }
  });

  return (
      <SideNav
      className="my-nav"
      isFixedNav
      expanded={true}
      isChildOfHeader={false}
      aria-label="Side navigation"
      >
        <SideNavItems>
          <SideNavMenuItem ref={(element) => menuRefs.current[0] = element} element={Link} to="page1">Page 1</SideNavMenuItem>
          <SideNavMenuItem ref={(element) => menuRefs.current[1] = element} element={Link} to="page2">Page 2</SideNavMenuItem>
          <SideNavMenu  title='Some submenu'>
            <SideNavMenuItem ref={(element) => menuRefs.current[2] = element} element={Link} to="page3">Page 3</SideNavMenuItem>
            <SideNavMenuItem ref={(element) => menuRefs.current[3] = element} element={Link} to="page4">Page 4</SideNavMenuItem>
            <SideNavMenuItem ref={(element) => menuRefs.current[4] = element} element={Link} to="page5">Page 5</SideNavMenuItem>
            <SideNavMenuItem ref={(element) => menuRefs.current[5] = element} element={Link} to="page6">Page 6</SideNavMenuItem>
            <SideNavMenuItem ref={(element) => menuRefs.current[6] = element} element={Link} to="page7">Page 7</SideNavMenuItem>
          </SideNavMenu>
          <SideNavMenuItem ref={(element) => menuRefs.current[7] = element} element={Link} to="page8">Page 8</SideNavMenuItem>
        </SideNavItems>
      </SideNav>
  );
};
4

2 回答 2

0

为了在用户使用内容 div 内的链接导航时打开树/跟踪项,我最终SideNavMenu用我自己的组件包装了原始项目,该组件递归地检查是否有任何子项具有指向当前位置的链接。我将检查分为三种方法,以避免if在其中任何一种中包含语句字段。我仍然不知道这是否是正确的方法,但它有效。

class MySideNavMenu extends React.Component {
  hasActiveChild = (child) => {
    if (child.props.element) { // leaf
      return this.props.location.pathname === child.props.to;
    }
    if (child.props.children) { // node
      return this.checkChildren(child.props.children);
    }
  };

  checkChildren = (children) => {
    return Array.isArray(children)
      ? children.some((child) => {
          return this.hasActiveChild(child);
        })
      : this.hasActiveChild(children);
  };

  isExpanded = () => {
    const children = this.props.children;
    if (children) {
      // if we have children, either a single or multiple, find if it is active
      return this.checkChildren(children);
    }

    return false;
  };

  render() {
    return (
      <SideNavMenu defaultExpanded={this.isExpanded()} title={this.props.title}>
        {this.props.children}
      </SideNavMenu>
    );
  }
}

export default withRouter(MySideNavMenu);
于 2021-06-16T04:50:52.400 回答
0

将活动项放在内存中并不是要走的路,afais,您应该从 url 推断它。您可以使用hashed routesorroute parameters来跟踪活动项目,单击后将其推送到 url,直接从组件中的 url 使用它。这样它就不会在刷新时丢失活动项目,并且 URL 也可以添加书签和共享。

于 2021-06-14T07:23:34.783 回答