【问题标题】:React JS Custom Sidebar NavigationReact JS 自定义侧边栏导航
【发布时间】:2021-10-05 07:26:17
【问题描述】:

我在 React APP 中创建了一个切换导航。一切正常,除了开关。下面是切换的代码。如果 parentId 存在,我正在使用对 parentId 的检查,然后包含子 ID,它将打开切换。如果不存在,则添加主 Id,其中一个是子项中的 parentId。

问题是我的 parentId 已经存在,如果我点击切换按钮,它不会关闭旧的并显示新的和旧的。

const handleArrowClick = ( data: CoursesNav ) => {
    const { id, parentId } = data;
    let newtoggledMenus = [...toggledMenus];
    if( parentId && newtoggledMenus.includes(parentId)){
        if (newtoggledMenus.includes(id)) {
            var index = newtoggledMenus.indexOf(id);
            if (index > -1) {
                newtoggledMenus.splice(index, 1);
            }
        } else {
            newtoggledMenus.push(id);
        }
        settoggledMenus(newtoggledMenus);
    }else{
        settoggledMenus([id]);
    }
};
    

我已经创建了下面给出的导航结构,其中在主要项目下添加了子项。

    export const CourseMenu = ( book: Book ): CoursesNav[] => {
        if( course ){
           // Chapters from book
            return book.chapters.map( c => {
                return {
                    id: c.id,
                    name: c.name,
                    link: `/my-book/${course.id}/chapter/${c.id}/edit`,
                    parentId: c.id,
                    // get topics and put under children
                    children: c.topics.map( m => {
                        return {
                            id: m.id,
                            name: m.name,
                            link: `/my-book/${course.id}/chapter/${c.id}/topics/${m.id}/edit`,
                            parentId: c.id,
                            //get blocks and put under blocks
                            children: m.blocks.map( b => {
                                return {
                                    id: b.id,
                                    name: b.title,
                                    link: `/my-book/${course.id}/chapter/${c.id}/topics/${m.id}/block/${b.id}/edit`,
                                    parentId: m.id
                                }
                            })
                        }
                    })
                }
            });
        }
    }

添加导航逻辑只是为了向您展示我正在尝试创建的内容。 每个父母都有用于切换的按钮来显示子项目。如果任何子项再次有子项,则会显示切换。

只有我在打开和关闭正确的切换时有问题。现在,如果我打开它的所有子项,则现在在一个主要子项下,前一个子项不会关闭,因为它们正在使 parentId 处于 toggledMenu 状态,这是一个数字数组。

【问题讨论】:

  • 你能用一些例子解释你的问题吗?事情还不清楚。
  • 您能否将您的问题的工作示例发布为stackblitz.com

标签: javascript reactjs


【解决方案1】:

我猜你在一本书中有一个 3 级层次结构 -> 章节、主题和块。单击(假设)右键时,您希望切换该特定项目的子项。这显然是在章节和主题级别。

一种解决方案是将您共享的整个层次结构(book.chapters)保持为一个状态,并在每个级别都有一个 showChildren 标志。

return book.chapters.map( c => {
                return {
                    id: c.id,
                    name: c.name,
                    link: `/my-book/${course.id}/chapter/${c.id}/edit`,
                    parentId: c.id,
                    showChildren: false,
                    // get topics and put under children
                    children: c.topics.map( m => {
                        return {
                            id: m.id,
                            name: m.name,

                            link: `/my-book/${course.id}/chapter/${c.id}/topics/${m.id}/edit`,
                            parentId: c.id,
                            showChildren: false,
                            //get blocks and put under blocks
                            children: m.blocks.map( b => {
                                return {
                                    id: b.id,
                                    name: b.title,
                                    link: `/my-book/${course.id}/chapter/${c.id}/topics/${m.id}/block/${b.id}/edit`,
                                    parentId: m.id
                                }
                            })
                        }
                    })
                }
            });
        }

根据点击右箭头,切换特定状态。

通过上述方法,您可以保持导航层次结构中的多个级别打开以进行切换。

【讨论】:

    【解决方案2】:

    兄弟,你为什么不使用 aria。不要搜索没有身体的父母。

    无论用户点击什么,用户都会点击您的按钮/链接,但您需要设置一个 aria 属性调用 aria-controls,您需要在其中放置要隐藏/显示的 eva 的值。

    首先关闭任何打开的菜单,然后等待 150 毫秒左右。只是为了防止您的循环关闭需要打开的循环

    function App () {
    /**
     * togging menus
     */
     function onClickHandler (e) {
      e.preventDefault();
      
      const btnPressed = e.target;
      
      // first you need to check if there is a item toggled and stuff.
      const openMenus = document.querySelectorAll("[aria-expanded]");
      
      if (openMenus.length) {
        Object.keys(openMenus).forEach(button => {
            const toggler = openMenus[button];
            
            const menuId = toggler.getAttribute("aria-controls");
            const menuToClose = document.getElementById(menuId);
            if (menuToClose && menuToClose !== null) {
              menuToClose.classList.remove("show");
              menuToClose.setAttribute("aria-hidden", "true");
              menuToClose.classList.add("hidden");
              
              // now the button
              toggler.setAttribute("aria-expanded", "false");
            }
        })
      }
      
              //wait a minute to prevent conflicts
            
            setTimeout(()=>{
                const toOpen = document.getElementById(btnPressed.getAttribute("aria-controls"));
                
                if (!toOpen) {return;}
                
                btnPressed.setAttribute("aria-expanded", "true");
                toOpen.classList.add("show");
              toOpen.setAttribute("aria-hidden", "false");
              toOpen.classList.remove("hidden");
              
            },[150])
    }
      
      
      return (
      <div className="accordion-example">
        <ul aria-label="Accordion Control Group Buttons" className="accordion-controls">
          <li>
            <button onClick={onClickHandler} aria-controls="content-1" aria-expanded="false" id="accordion-control-1">Apples</button>
            <div className="menu hidden" aria-hidden="true" id="content-1">
              <p>Apples are a fine fruit often associated with good health, and fewer doctor's appointments.</p>
              <p>Example. An apple a day keeps the doctor away.</p>
            </div>
          </li>
      
          <li>
            <button onClick={onClickHandler} aria-controls="content-2" aria-expanded="false" id="accordion-control-2">Lemons</button>
            <div className="menu hidden" aria-hidden="true" id="content-2">
              <p>Lemons are good with almost anything, yet are often have a negative connotation when used in conversation.</p>
              <p>Example. The bread from the french bakery is normally very good, but the one we bought today was a lemon.</p>
            </div>
          </li>
      
          <li>
            <button onClick={onClickHandler} aria-controls="content-3" aria-expanded="false" id="accordion-control-3">Kiwis</button>
            <div className="menu hidden" aria-hidden="true" id="content-3">
              <p>Kiwis are a fun, under-appreciated fruit.</p>
            </div>
          </li>
        </ul>
      </div>)
      }
    
    
    
    ReactDOM.render( < App / > , document.getElementById("page"));
    .hidden {
      display: none;
    }
    
    .show {
      display: blocK
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
    
    
    <div id="page"></div>

    【讨论】:

    • 您分享的上述示例不起作用。你将如何处理嵌套的手风琴。我想知道谁对这个答案投了赞成票。
    • @vikasdhiman 你从来没有提到过嵌套。
    • 在我的数据中,孩子们显然是可用的,而且是两次。我想你完全错过了。
    • 现在我明白你为什么需要问这类问题了
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-26
    • 1970-01-01
    • 1970-01-01
    • 2014-07-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多