Javascript 渲染后如何将焦点设置在输入字段上?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/28889826/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 02:33:04  来源:igfitidea点击:

How to set focus on an input field after rendering?

javascriptreactjs

提问by Dave

What's the react way of setting focus on a particular text field after the component is rendered?

在组件呈现后将焦点设置在特定文本字段上的反应方式是什么?

Documentation seems to suggest using refs, e.g:

文档似乎建议使用 refs,例如:

Set ref="nameInput"on my input field in the render function, and then call:

ref="nameInput"在渲染函数中设置我的输入字段,然后调用:

this.refs.nameInput.getInputDOMNode().focus(); 

But where should I call this? I've tried a few places but I cannot get it to work.

但是我应该在哪里称呼它?我已经尝试了几个地方,但我无法让它工作。

回答by Brigand

@Dhiraj's answer is correct, and for convenience you can use the autoFocus prop to have an input automatically focus when mounted:

@Dhiraj 的回答是正确的,为方便起见,您可以使用 autoFocus 道具让输入在安装时自动聚焦:

<input autoFocus name=...

Note that in jsx it's autoFocus(capital F) unlike plain old html which is case-insensitive.

请注意,在 jsx 中,它autoFocus(大写 F)与不区分大小写的普通旧 html 不同。

回答by Dhiraj

You should do it in componentDidMountand refs callbackinstead. Something like this

你应该在componentDidMountrefs callback不是这样做。像这样的东西

componentDidMount(){
   this.nameInput.focus(); 
}

class App extends React.Component{
  componentDidMount(){
    this.nameInput.focus();
  }
  render() {
    return(
      <div>
        <input 
          defaultValue="Won't focus" 
        />
        <input 
          ref={(input) => { this.nameInput = input; }} 
          defaultValue="will focus"
        />
      </div>
    );
  }
}
    
ReactDOM.render(<App />, document.getElementById('app'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.3.1/react.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.3.1/react-dom.js"></script>
<div id="app"></div>

回答by Ilya Semenov

As of React 0.15, the most concise method is:

从 React 0.15 开始,最简洁的方法是:

<input ref={input => input && input.focus()}/>

回答by Ben Carp

Focus on mount

专注于坐骑

If you just want to focus an element when it mounts (initially renders) a simple use of the autoFocus attribute will do.

如果您只想在元素挂载(最初呈现)时聚焦它,只需简单地使用 autoFocus 属性即可。

<input type="text" autoFocus />

Dynamic focus

动态对焦

to control focus dynamically use a general function to hide implementation details from your components.

要动态控制焦点,请使用通用函数来隐藏组件的实现细节。

React 16.8 + Functional component - useFocus hook

React 16.8 + 函数式组件 - useFocus hook

const FocusDemo = () => {

    const [inputRef, setInputFocus] = useFocus()

    return (
        <> 
            <button onClick={setInputFocus} >
               FOCUS
            </button>
            <input ref={inputRef} />
        </>
    )

}

const useFocus = () => {
    const htmlElRef = useRef(null)
    const setFocus = () => {htmlElRef.current &&  htmlElRef.current.focus()}

    return [ htmlElRef, setFocus ] 
}

Full Demo

完整演示

React 16.3 + Class Components - utilizeFocus

React 16.3 + 类组件——利用焦点

class App extends Component {
  constructor(props){
    super(props)
    this.inputFocus = utilizeFocus()
  }

  render(){
    return (
      <> 
          <button onClick={this.inputFocus.setFocus}>
             FOCUS
          </button>
          <input ref={this.inputFocus.ref}/>
      </>
    )
  } 
}
const utilizeFocus = () => {
    const ref = React.createRef()
    const setFocus = () => {ref.current &&  ref.current.focus()}

    return {setFocus, ref} 
}

Full Demo

完整演示

回答by Hyman Lee

If you just want to make autofocus in React, it's simple.

如果你只想在 React 中实现自动对焦,这很简单。

<input autoFocus type="text" />


While if you just want to know where to put that code, answer is in componentDidMount().

如果您只想知道将该代码放在哪里,则答案在 componentDidMount() 中。

v014.3

v014.3

componentDidMount() {
    this.refs.linkInput.focus()
}

In most cases, you can attach a ref to the DOM node and avoid using findDOMNode at all.

在大多数情况下,您可以将 ref 附加到 DOM 节点并完全避免使用 findDOMNode。

Read the API documents here: https://facebook.github.io/react/docs/top-level-api.html#reactdom.finddomnode

在此处阅读 API 文档:https: //facebook.github.io/react/docs/top-level-api.html#reactdom.finddomnode

回答by ettanany

React 16.3added a new convenient way to handle this by creating a ref in component's constructor and use it like below:

React 16.3通过在组件的构造函数中创建一个 ref 并像下面这样使用它,添加了一种新的方便的方法来处理这个问题:

class MyForm extends Component {
  constructor(props) {
      super(props);

      this.textInput = React.createRef();
  }

  componentDidMount() {
    this.textInput.current.focus(); // one important change here is that we need to access the element via current.
  }

  render() {
    // instead of using arrow function, the created ref can be used directly.
    return(
      <div>
        <input ref={this.textInput} />
      </div>
    );
  }
}

For more details, you can check this articlein React blog.

有关更多详细信息,您可以查看React 博客中的这篇文章

Update:

更新:

Starting from React 16.8, useRefhook can be used in function components to achieve the same result:

从 React 16.8开始,useRef可以在函数组件中使用 hook 来达到相同的效果:

import React, { useEffect, useRef } from 'react';

const MyForm = () => {
  const textInput = useRef(null);

  useEffect(() => {
    textInput.current.focus();
  }, []);

  return (
    <div>
      <input ref={textInput} />
    </div>
  );
};

回答by jmbertucci

I just ran into this issue and I'm using react 15.0.115.0.2 and I'm using ES6 syntax and didn't quite get what I needed from the other answers since v.15 dropped weeks ago and some of the this.refsproperties were deprecatedand removed.

我刚刚遇到了这个问题,我正在使用 react 15.0.115.0.2 并且我使用的是 ES6 语法并且没有完全从其他答案中得到我需要的东西,因为 v.15 几周前下降了一些this.refs属性被弃用删除

In general, what I needed was:

一般来说,我需要的是:

  1. Focus the first input (field) element when the component mounts
  2. Focus the first input (field) element with an error (after submit)
  1. 组件挂载时聚焦第一个输入(字段)元素
  2. 聚焦有错误的第一个输入(字段)元素(提交后)

I'm using:

我正在使用:

  • React Container/Presentation Component
  • Redux
  • React-Router
  • 反应容器/演示组件
  • 终极版
  • 反应路由器

Focus the First Input Element

聚焦第一个输入元素

I used autoFocus={true}on the first <input />on the page so that when the component mounts, it will get focus.

我在页面autoFocus={true}上的第一个<input />使用,以便当组件安装时,它会获得焦点。

Focus the First Input Element with an Error

聚焦第一个有错误的输入元素

This took longer and was more convoluted. I'm keeping out code that isn't relevant to the solution for brevity.

这花费了更长的时间并且更加复杂。为简洁起见,我保留了与解决方案无关的代码。

Redux Store / State

Redux 存储/状态

I need a global state to know if I should set the focus and to disable it when it was set, so I don't keep re-setting focus when the components re-render (I'll be using componentDidUpdate()to check for setting focus.)

我需要一个全局状态来知道我是否应该设置焦点并在设置时禁用它,所以当组件重新渲染时我不会一直重新设置焦点(我将componentDidUpdate()用来检查设置焦点。 )

This could be designed as you see fit for you application.

这可以设计为您认为适合您的应用程序。

{
    form: {
        resetFocus: false,
    }
}

Container Component

容器组件

The component will need to have the resetfocusproperty set and a callBack to clear the property if it ends up setting focus on itself.

如果组件resetfocus最终将焦点设置在自身上,则该组件将需要设置属性和回调以清除该属性。

Also note, I organized my Action Creators into separate files mostly due to my project is fairly large and I wanted to break them up into more manageable chunks.

另请注意,我将我的 Action Creator 组织成单独的文件,主要是因为我的项目相当大,我想将它们分解成更易于管理的块。

import { connect } from 'react-redux';
import MyField from '../presentation/MyField';
import ActionCreator from '../actions/action-creators';

function mapStateToProps(state) {
    return {
        resetFocus: state.form.resetFocus
    }
}

function mapDispatchToProps(dispatch) {
    return {
        clearResetFocus() {
            dispatch(ActionCreator.clearResetFocus());
        }
    }
}

export default connect(mapStateToProps, mapDispatchToProps)(MyField);

Presentation Component

演示组件

import React, { PropTypes } form 'react';

export default class MyField extends React.Component {
    // don't forget to .bind(this)
    constructor(props) {
        super(props);
        this._handleRef = this._handleRef.bind(this);
    }

    // This is not called on the initial render so
    // this._input will be set before this get called
    componentDidUpdate() {
        if(!this.props.resetFocus) {
            return false;
        }

        if(this.shouldfocus()) {
            this._input.focus();
            this.props.clearResetFocus();
        }
    }

    // When the component mounts, it will save a 
    // reference to itself as _input, which we'll
    // be able to call in subsequent componentDidUpdate()
    // calls if we need to set focus.
    _handleRef(c) {
        this._input = c;
    }

    // Whatever logic you need to determine if this
    // component should get focus
    shouldFocus() {
        // ...
    }

    // pass the _handleRef callback so we can access 
    // a reference of this element in other component methods
    render() {
        return (
            <input ref={this._handleRef} type="text" />
        );
    }
}

Myfield.propTypes = {
    clearResetFocus: PropTypes.func,
    resetFocus: PropTypes.bool
}

Overview

概述

The general idea is that each form field that could have an error and be focused needs to check itself and if it needs to set focus on itself.

一般的想法是,每个可能有错误并被聚焦的表单字段都需要检查自己,以及它是否需要将焦点设置在自己身上。

There's business logic that needs to happen to determine if the given field is the right field to set focus to. This isn't shown because it will depend on the individual application.

需要发生业务逻辑来确定给定字段是否是设置焦点的正确字段。这未显示,因为它将取决于单个应用程序。

When a form is submitted, that event needs to set the global focus flag resetFocusto true. Then as each component updates itself, it will see that it should check to see if it gets the focus and if it does, dispatch the event to reset focus so other elements don't have to keep checking.

提交表单时,该事件需要将全局焦点标志设置resetFocus为 true。然后当每个组件更新自身时,它会看到它应该检查它是否获得焦点,如果获得焦点,则调度事件以重置焦点,因此其他元素不必继续检查。

editAs a side note, I had my business logic in a "utilities" file and I just exported the method and called it within each shouldfocus()method.

编辑作为旁注,我在“实用程序”文件中有我的业务逻辑,我只是​​导出该方法并在每个shouldfocus()方法中调用它。

Cheers!

干杯!

回答by Kevin Suttle

The React docs now have a section for this. https://facebook.github.io/react/docs/more-about-refs.html#the-ref-callback-attribute

React 文档现在有一个部分。https://facebook.github.io/react/docs/more-about-refs.html#the-ref-callback-attribute

 render: function() {
  return (
    <TextInput
      ref={function(input) {
        if (input != null) {
          input.focus();
        }
      }} />
    );
  },

回答by GAEfan

This is not longer the best answer. As of v0.13, this.refsmay not available until AFTER componentDidMount()runs, in some odd cases.

这不再是最佳答案。从 v0.13this.refs开始componentDidMount(),在某些奇怪的情况下,在AFTER运行之前可能无法使用。

Just add the autoFocustag to your input field, as FakeRainBrigand showed above.

只需将autoFocus标签添加到您的输入字段,如 FakeRainBrigand 上面所示。

回答by o01

Ref. @Dave's comment on @Dhiraj's answer; an alternative is to use the callback functionality of the ref attribute on the element being rendered (after a component first renders):

参考 @Dave 对 @Dhiraj 的回答的评论;另一种方法是在正在呈现的元素上使用 ref 属性的回调功能(在组件首次呈现之后):

<input ref={ function(component){ React.findDOMNode(component).focus();} } />

More info

更多信息