【问题标题】:Focus on newly-rendered text input after tab-fired blur event在标签触发的模糊事件后关注新渲染的文本输入
【发布时间】:2017-03-18 20:16:19
【问题描述】:

我有一个带有文本输入的 React (15.3.2) 组件。

(我在这里说“渲染”的地方实际上是渲染或取消隐藏;我都试过了。)

当输入元素被模糊时,我会渲染一个带有文本输入的新组件。

我想给新的文本输入焦点。

我试过componentDidMountcomponentWillUpdatecomponentDidUpdate;我试过命名和功能refs;我试过 react-dom。

聚焦本身可以工作,例如,一旦它被渲染,如果我点击初始输入,焦点就会转到新输入(这是一个错误,但与聚焦相比,微不足道)。

第一个输入有一个onBlur,它设置用于告诉第二个输入渲染与否的状态。

在那个模糊处理程序中,我尽我所能停止事件。

当我跳出第一个元素时,我已经“过去”了新渲染的元素,例如,我当前裸设计中的浏览器标签栏——我猜新元素还没有被渲染?

class SecondInput extends Component {
  componentDidUpdate = (prevProps, prevState) => {
    if (!this.props.hidden) this._input.focus()
  }

  render = () => 
    <input type="text" hidden={this.props.hidden} ref={(c) => this._input = c}
}

class NewItem extends Component {
  state = { itemEntered: false }

  itemBlurred = (e) => {
    e.preventDefault()
    e.stopPropagation()
    this.setState({ itemEntered: true })
  }

  render = () =>
    <div>
      Item: <input type="text" onBlur={this.itemBlurred} />
      <SecondInput hidden={!this.state.itemEntered} />
    </div>
}

有什么想法或提示吗?我必须相信这是显而易见的事情,因为这肯定一直在发生。

我也对任何其他形式的组件层次结构持开放态度,例如,如果我需要一个容器来以某种方式包装所有这些东西,那很好。

反应 15.3.2

【问题讨论】:

    标签: javascript reactjs


    【解决方案1】:

    您看到的问题似乎是因为当您按 Tab 时页面上没有更多可聚焦的元素,因此焦点转到地址栏。出于某种原因,当焦点位于地址栏时,仅调用 this._input.focus() 不会像您期望的那样获取焦点。

    为了解决这个问题,我添加了一个空 div,并根据是否显示第二个输入来设置tabIndex 属性。

    为了让我自己更轻松,我将输入焦点放在了 mount 上,而不是使用 hidden 属性。这在您的情况下可能有效,也可能无效,但它似乎更干净,因为如果输入是受控输入,它会阻止输入在每次按键上调用焦点。

    let Component = React.Component;
    
    
    class SecondInput extends Component {
      componentDidMount(){
        this.textInput.focus()
      }
    
      render(){
        return (
          <input type="text" ref={(input) => this.textInput = input} />
        )
      }
    }
    
    class NewItem extends Component {
      state = { itemEntered: false }
    
      itemBlurred = (e) => {
        //e.preventDefault()
        //e.stopPropagation()
        this.setState({ itemEntered: true })
      }
    
      render = () =>
        <div>
          Item: <input type="text" onBlur={this.itemBlurred} />
          {
            this.state.itemEntered ? [
              <SecondInput/>
            ] : []
           }
           <div tabIndex={this.state.itemEntered ? null :  0}/>
        </div>
    }
    
    ReactDOM.render(<NewItem />, document.body);
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.3.0/react.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.3.0/react-dom.min.js"></script>

    【讨论】:

    • 谢谢!在一个页面上有多个tabIndex=0 是否有影响?例如,如果页面上有多个NewItem 组件怎么办?
    • tabIndex=0 就像一个输入,所以你可以添加多个,但是你只需要在当前一个焦点目标之后至少有一个焦点目标。
    • 如果您使用隐藏方法而不是仅仅不呈现表单,您可以将输入包装在带有tabIndex={this.props.hidden?1:0}的div中
    • @DaveNewton,不确定你看到了,但我回答了你的评论。
    • 是的,我做到了,再次感谢 - 只是还没来得及标记接受。当它不是一个实际问题而更多是一个孤立的尝试问题时,这是令人沮丧的:/
    猜你喜欢
    • 2020-04-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-05
    • 1970-01-01
    • 2018-08-09
    • 2014-05-29
    • 1970-01-01
    相关资源
    最近更新 更多