从其他子组件采取行动后,在子组件中反应焦点项目列表

时间:2018-11-15 20:35:17

标签: reactjs

编辑:虽然Sung Kim的答案对于原始情况是正确的,但我忘记补充一点,例如(可以从列表中选择下一项)此行为可以通过其他一些键来切换ArrowDown,在这种情况下,tabIndex至少起初不会有太大帮助。

``````````````````````````````````````````````` `````````````````````````````````````````````````` ````''``

我正在尝试一个具有两个单独的(同级)功能组件的下拉组件。第一个是常规<input>,它将接受一个值。 第二个是<ul>,将显示结果。

流程是,最初只显示<input>,当您键入并从数据库中获取结果时,然后会显示<ul>

以上功能已经完成,但是,我现在要完成的工作是,当我完成键入操作(因为我对看到的结果感到满意)并点击tab时,则第一个项目结果列表中的数据(恰好位于<a>中的<li>上),然后,如果我继续命中tab,则最后一个的下一个项目将聚焦,依此类推,直到达到最后的项目。

因此,本质上,焦点动作可能来自于在输入上单击选项卡,或者来自当前列表项(如果已被聚焦)。

我一直在考虑最干净的方法来使它生效。我认为也许通过refcreateRef使用forwardRed可能是一个好主意,但老实说我暂时无法解决这个问题,所以我认为自己可以伸出援手寻求帮助。

这基本上是它的样子(一切都按预期工作,我从几乎所有逻辑上将其分解为基本内容,并专注于此处的主要问题,这就是重点...)

父项:

class Parent extends React.Component {
  componentDidMount() {}

  handleInternalKeyPress = (e) => {
    if (e.key === 'Tab') {
      e.preventDefault()
      // do something?
    }
  }

  render() {
    return (
      <section>
        <section>
          <DropdownInput
            handleTextChange={this.props.handleTextChange}
            handleKeyDown={this.handleInternalKeyPress}
          />
          <DropdownResults
            results={this.props.results}
            handleKeyDown={this.handleInternalKeyPress}
          />
        </section>
      </section>
    )
  }
}

输入组件:

const DropdownInput = props => (
  <Input
    onChange={e => props.handleTextChange(e)}
    onKeyDown={e => props.handleKeyDown(e)}
    type="text"
  />
)

结果组件(<ul>):

// Maybe this should be a React.forwardRef() instead of
// an arrow function, but I'm not sure if this is the
// best/most elegant approach
const DropdownResults = props => (
  <ul>
    {props.results.map((result, i) => (
      <li key={result.resultIdKey}>
        <a
          // perhaps a ref should go in here?
          onKeyDown={e => props.handleKeyDown(e)}
          role="link"
          tabIndex={i}
        >
          {result.resultTitleDisplayKey}
        </a>
      </li>
    ))}
  </ul>
)

同样,组件要比这复杂得多,但这是它们如何工作的基本思想。

例如,最好抓住焦点的项目为其设置自定义样式。

我一直在想一想,但是这个想法确实让我受益匪浅,特别是因为我想遵守最佳/最新的React惯例,因此能提供的任何帮助将不胜感激!

1 个答案:

答案 0 :(得分:1)

我从没用过tabIndex,而是在看了一些文章之后玩了。

设置tabIndex={0}似乎有效,而不是使用i来提高它。

const DropdownResults = props => (
  <ul>
    {props.results.map((result, i) => (
      <li key={result.resultIdKey}>
        <a
          // perhaps a ref should go in here?
          onKeyDown={e => props.handleKeyDown(e)}
          role="link"
          tabIndex={0}
        >
          {result.resultTitleDisplayKey}
        </a>
      </li>
    ))}
  </ul>
);

demo

出于某种原因,Google文档(Using tabindex)表示使用tabIndex大于0是一个反模式,没有太多解释(以及此older blog post,也没有解释为什么也不))< / p>

即使MDN documentation并没有说出使用tabIndex大于0作为反模式。

但是目前看来,设置tabIndex=0的所有值似乎都可以。

您可以分叉代码。
Edit 002pz9kp20