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

2020/09/22 20:01 · javascript ·  · 0评论

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

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

ref="nameInput"在渲染功能中的输入字段上进行设置,然后调用:

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

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

您应该这样做,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>

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

<input autoFocus name=...

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

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

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

专注于坐骑

如果只想在挂载(初始渲染)时聚焦某个元素,则只需使用autoFocus属性即可。

<input type="text" autoFocus />

动态焦点

要动态控制焦点,请使用常规功能从组件中隐藏实现细节。

React 16.8 +功能组件-useFocus挂钩

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 ] 
}

完整演示

React 16.3 +类组件-exploitFocus

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} 
}

完整演示

如果您只想在React中进行自动对焦,那很简单。

<input autoFocus type="text" />

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

v014.3

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

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

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

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>
    );
  }
}

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

更新:

从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>
  );
};

我刚遇到这个问题,我使用的是React 15.0.1 15.0.2,我使用的是ES6语法,但从v.15几周前删除了一些this.refs属性以来,我并没有从其他答案中得到所需的东西已弃用移除

总的来说,我需要的是:

  1. 安装组件时,集中第一个输入(字段)元素
  2. 将第一个输入(字段)元素聚焦于一个错误(提交之后)

我正在使用:

  • React容器/演示组件
  • Redux
  • 反应路由器

关注第一个输入元素

在页面autoFocus={true}的第一个<input />使用过,以便在安装组件时将其聚焦。

使第一个输入元素出现错误

这花费了更长的时间并且更加令人费解。我保留与简洁解决方案无关的代码。

Redux商店/州

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

可以按照您认为适合自己的应用程序进行设计。

{
    form: {
        resetFocus: false,
    }
}

容器组件

如果组件resetfocus最终将焦点放在自身上,则需要设置属性和一个CallBack来清除该属性。

还要注意,由于我的项目相当大,我将动作创建者组织到了单独的文件中,我想将它们分解为更易于管理的块。

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);

演示组件

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
}

总览

通常的想法是,每个可能有错误并被关注的表单域都需要检查自身,以及是否需要将焦点放在自身上。

需要确定确定给定字段是否是设置焦点的正确字段的业务逻辑。由于依赖于各个应用程序,因此未显示。

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

编辑
作为一个附带说明,我将业务逻辑存储在“实用程序”文件中,我只是导出了该方法,并在每个
shouldfocus()方法中对其进行了调用

干杯!

现在,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();
        }
      }} />
    );
  },

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

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

参考 @Dave对@Dhiraj答案的评论;一种替代方法是在要渲染的元素上使用ref属性的回调功能(在组件首次渲染之后):

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

更多信息

这是自动对焦的正确方法。当使用回调而不是字符串作为参考值时,将自动调用它。您可以获得参考,而不需要使用来接触DOM。getDOMNode

render: function() {
  return <TextInput ref={(c) => this._input = c} />;
},
componentDidMount: function() {
  this._input.focus();
},

请注意,这些答案均不适用于material-ui TextField组件如何将焦点设置为materialUI TextField?我必须跳过一些箍才能使它起作用:

const focusUsernameInputField = input => {
  if (input) {
    setTimeout(() => {input.focus()}, 100);
  }
};

return (
  <TextField
    hintText="Username"
    floatingLabelText="Username"
    ref={focusUsernameInputField}
  />
);

您可以将该方法调用放入render函数中。或在生命周期方法中,componentDidUpdate

你不需要getInputDOMNode?? 在这种情况下...

只需在安装组件时获取它reffocus()它-componentDidMount ...

import React from 'react';
import { render } from 'react-dom';

class myApp extends React.Component {

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

  render() {
    return(
      <div>
        <input ref={input => { this.nameInput = input; }} />
      </div>
    );
  }

}

ReactDOM.render(<myApp />, document.getElementById('root'));

AutoFocus最适合我。我需要双击将某些文本更改为带有该文本的输入,所以最终得到的结果是:

<input autoFocus onFocus={this.setCaretToEnd} value={this.state.editTodo.value} onDoubleClick={this.updateTodoItem} />

注:要解决React将插入记号放在文本开头的问题,请使用以下方法:

setCaretToEnd(event) {
    var originalText = event.target.value;
    event.target.value = '';
    event.target.value = originalText;
}

在这里找到:https :
//coderwall.com/p/0iz_zq/how-to-put-focus-at-the-end-of-an-input-with-react-js

我有同样的问题,但我也有一些动画,所以我的同事建议使用window.requestAnimationFrame

这是我元素的ref属性:

ref={(input) => {input && window.requestAnimationFrame(()=>{input.focus()})}}

警告:ReactDOMComponent:不要访问DOM节点的.getDOMNode()。而是直接使用该节点。此DOM节点由渲染App

应该

componentDidMount: function () {
  this.refs.nameInput.focus();
}

最简单的答案是在输入文本元素中添加ref =“ some name”并调用以下函数。

componentDidMount(){
   this.refs.field_name.focus();
}
// here field_name is ref name.

<input type="text" ref="field_name" />

要将焦点移到新创建的元素上,可以将元素的ID存储在状态中,并使用它来设置autoFocus例如

export default class DefaultRolesPage extends React.Component {

    addRole = ev => {
        ev.preventDefault();
        const roleKey = this.roleKey++;
        this::updateState({
            focus: {$set: roleKey},
            formData: {
                roles: {
                    $push: [{
                        id: null,
                        name: '',
                        permissions: new Set(),
                        key: roleKey,
                    }]
                }
            }
        })
    }

    render() {
        const {formData} = this.state;

        return (
            <GridForm onSubmit={this.submit}>
                {formData.roles.map((role, idx) => (
                    <GridSection key={role.key}>
                        <GridRow>
                            <GridCol>
                                <label>Role</label>
                                <TextBox value={role.name} onChange={this.roleName(idx)} autoFocus={role.key === this.state.focus}/>
                            </GridCol>
                        </GridRow>
                    </GridSection>
                ))}
            </GridForm>
        )
    }
}

这样,所有文本框都不会集中在页面加载上(就像我想要的那样),但是当您按下“添加”按钮来创建新记录时,该新记录就会得到关注。

由于autoFocus除非重新安装该组件,否则它不会再次“运行”,因此我不必费心设置this.state.focus(即,在更新其他状态时,它将不会继续窃取焦点)。

使用带有Typescript的React Hooks / Functional组件,您可以将useRefhookHTMLInputElement用作以下参数的通用参数useRef

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

export default function MyComponent(): JSX.Element {
    const inputReference = useRef<HTMLInputElement>(null);

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

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

或者,如果使用reactstrap,则提供inputReferenceinnerRef而不是ref

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

export default function MyComponent(): JSX.Element {
    const inputReference = useRef<HTMLInputElement>(null);

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

    return (
        <div>
            <Input innerRef={inputReference} />
        </div>
    );
}

阅读几乎所有答案,但没有看到 getRenderedComponent().props.input

设置文本输入参考

this.refs.username.getRenderedComponent().props.input.onChange('');

在尝试了许多以上选项但没有成功之后,我发现它是我原来的样子disabling,然后enabling输入导致焦点丢失。

我有一个道具sendingAnswer,可以在轮询后端时禁用输入。

<Input
  autoFocus={question}
  placeholder={
    gettingQuestion ? 'Loading...' : 'Type your answer here...'
  }
  value={answer}
  onChange={event => dispatch(updateAnswer(event.target.value))}
  type="text"
  autocomplete="off"
  name="answer"
  // disabled={sendingAnswer} <-- Causing focus to be lost.
/>

一旦我移除了禁用的道具,一切都会重新开始。

根据更新的语法,您可以使用 this.myRref.current.focus()

更新版本可以在这里查看

componentDidMount() {

    // Focus to the input as html5 autofocus
    this.inputRef.focus();

}
render() {
    return <input type="text" ref={(input) => { this.inputRef = input }} />
})

由于造成此错误的原因很多,我认为我也应该发布我面临的问题。对我来说,问题在于我将输入作为另一个组件的内容进行渲染。

export default ({ Content }) => {
  return (
  <div className="container-fluid main_container">
    <div className="row">
      <div className="col-sm-12 h-100">
        <Content />                                 // I rendered my inputs here
      </div>
    </div>
  </div>
  );
}

这就是我调用上述组件的方式:

<Component Content={() => {
  return (
    <input type="text"/>
  );
}} />
<input type="text" autoFocus />

总是先尝试简单且基本的解决方案,对我有用。

本文地址:http://javascript.askforanswer.com/xuanranhouruhezaishuruziduanshangshezhijiaodian.html
文章标签: ,  
版权声明:本文为原创文章,版权归 javascript 所有,欢迎分享本文,转载请保留出处!

文件下载

老薛主机终身7折优惠码boke112

上一篇:
下一篇:

评论已关闭!