React:如何使用箭头键移动焦点?(TreeView)

8

我正在寻找一种解决方案,允许使用箭头键集中树视图内的元素。

目前,我有一个 treeView(ul) 和 treeNode(li)。每个treeNode 可能有自己的 treeView 等等。每个 treeNode 都有tabIndex="0" 属性,以添加通过Tab键在 treeView 中导航的可能性。它工作得很好。但是我想添加键盘箭头支持做同样的事情。

您有任何想法如何实现吗? 附言:除了纯React和JS外,我不想使用任何第三方库。

<section>
  <header>
    { title }
  </header>
  <ul>
    <li>
      <section>
        <header>
          { title }
        </header>
        <ul>
          // etc.
        </ul>
      </section>
    </li>
  </ul>
<section>

2个回答

5
我已经找到了一种在treeView内移动焦点的解决方案。 首先,您应该找到树中的所有节点。 然后,您可以使用document.activeElement查找聚焦元素。之后,您可以在节点数组中找到此项(document.activeElement == nodes[i]),并记住索引i。要使用箭头键移动焦点,只需将eventListener添加到节点并处理它即可。
例如,要向上移动,可以执行以下操作:if(arrowUp) { elements[i + 1].focus() }

1

Roman的答案很有帮助。我进一步创建了处理向上或向下移动焦点的函数。

在组件中,我在onKeyDown事件上调用handleKeyDown函数:

<UnorderedList id='unordered-list' onKeyDown={handleKeyDown} />

为了调用这些函数,我在我的onKeyDown处理程序中使用了如下的if语句:
    const handleKeyDown = (e) => {
    if(e.key === 'ArrowDown') {
        moveFocusDown()
    }
    if(e.key === 'ArrowUp') {
        moveFocusUp()
    }
}

接下来是moveFocusDown函数,我完成了以下操作:

    const moveFocusDown = () => {
    const listItems = document.querySelector('#unordered-list').childNodes
    const activeItem = document.activeElement
    for(let i = 0; i < listItems.length; i++) {

        const listLength = listItems.length
       if(activeItem === listItems[i] && activeItem !== listItems[listLength - 1]) {
        listItems[i + 1].focus()
       }
    }
}

条件语句activeItem === listItems[i] && activeItem !== listItems[listLength - 1]检查当前活动项和无序列表子节点的当前索引是否相同,然后检查节点列表中的最后一个元素不是活动元素。这是为了防止将焦点移动到不存在的元素上。

moveFocus up函数稍微简单一些:

    const moveFocusUp = () => {
    const listItems = document.querySelector('#menu').childNodes
    const activeItem = document.activeElement
    for(let i = 0; i < listItems.length; i++) {
       if(activeItem === listItems[i] && activeItem !== listItems[0]) {
        listItems[i - 1].focus()
       }
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接