【问题标题】:How do you focus and select an input when it loads?加载时如何聚焦和选择输入?
【发布时间】:2020-12-25 09:08:58
【问题描述】:

对于加载时聚焦和选择输入元素的问题,我无法找到好的答案;最初我只使用了一个 useRef(),将其设置为 ref,然后在组件加载 (useEffect(,[])) 时我会 ref.current.focus() / ref.current.select()。但是 input 内置的 autoFocus 和 onFocus 是更简单的解决方案。

换句话说,考虑下面的代码sn-p,当你按下按钮时,我们想要关注输入(在这里不起作用)

// Get hook functions (specific for use with stackoverflow code snippet)
const { useState } = React;

const Example = ({title}) => {
  // hook that keeps track of the editing state
  const [editing, setEditing] = useState(false);
  
  // switch to input when button is pressed
  const InputComponent = () => {
    if (!editing) { 
     return ( <span>click for input</span>)
    }
    else {
      return ( <input /> )
    }
  }

  return (
    <div>
      <p>{title}</p>
      <p>{InputComponent()}</p>
      <button onClick={() => setEditing(!editing)}>
        Click me
      </button>
    </div>
  );
};

// Render it
ReactDOM.render(
  <Example title="The goal is to have the input automatically focused" />,
  document.getElementById("react")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="react"></div>

现在,如果我们使用引用

const { useState, useRef, useEffect } = React;

const Example = ({title}) => {
  const [editing, setEditing] = useState(false);
  // useRef for a reference to the input
  const inputRef = useRef();

  const InputComponent = () => {
    if (!editing) { 
     return ( <span>click for input</span>)
    }
    else {
      // set the ref as a reference to the input
      return ( <input ref={inputRef}/> )
    }
  }
  
  // when editing updates, run this code
  useEffect(() => {
    // when editing is true, focus the input
    if (editing) {inputRef.current.focus()}
  }, [editing])

  return (
    <div>
      <p>{title}</p>
      <p>{InputComponent()}</p>
      <button onClick={() => setEditing(!editing)}>
        Click me
      </button>
    </div>
  );
};

// Render it
ReactDOM.render(
  <Example title="The goal is to have the input automatically focused" />,
  document.getElementById("react")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="react"></div>

如果您想在输入焦点时选择输入的值,您可以执行以下操作:

const { useState, useRef, useEffect } = React;

const Example = ({title}) => {
  const [editing, setEditing] = useState(false);
  // define a state variable for the input value
  const [inputValue, setValue] = useState("value of the input");
  const inputRef = useRef();

  const InputComponent = () => {
    if (!editing) { 
     return ( <span>click for input</span>)
    }
    else {
      
      return ( 
        <input 
        ref={inputRef} 
        // define the value of the input
        value={inputValue}
        // when the input is changed, update the state variable
        onChange={(event) => setValue(event.target.value)}
        /> 
      )
    }
  }
  
  useEffect(() => {
    if (editing) {
      inputRef.current.focus();
      // focus and select the value of the input
      inputRef.current.select();
    }
  }, [editing])

  return (
    <div>
      <p>{title}</p>
      <p>{InputComponent()}</p>
      <button onClick={() => setEditing(!editing)}>
        Click me
      </button>
    </div>
  );
};

// Render it
ReactDOM.render(
  <Example title="The goal is to have the input automatically focused" />,
  document.getElementById("react")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="react"></div>

此方法允许您设置输入的一些基本值(例如表示值的程式化方式,然后当用户单击该程式化值时,它开始编辑)。

这个解决方案很好,但它很笨重,并且在某些情况下需要您将引用向下传递给组件,而且通常不干净。那么有没有更好的解决方案呢?是的……

【问题讨论】:

    标签: javascript reactjs select input


    【解决方案1】:

    这是一个简化版本,可以实现相同的效果,但要简单得多

    const { useState, useRef, useEffect } = React;
    
    const Example = ({title}) => {
      const [editing, setEditing] = useState(false);
      const [inputValue, setValue] = useState("value of the input");
      // no need for a reference
    
      const InputComponent = () => {
        if (!editing) { 
         return ( <span>click for input</span>)
        }
        else {
          return ( 
            <input 
              // don't need to set an input reference
              onChange={(event) => setValue(event.target.value)}
              value={inputValue}
              onFocus={(event) => event.target.select()} // selects the value on load
              autoFocus // focuses on load
            /> 
          )
        }
      }
      
      // no need for a useEffect
      return (
        <div>
          <p>{title}</p>
          <p>{InputComponent()}</p>
          <button onClick={() => setEditing(!editing)}>
            Click me
          </button>
        </div>
      );
    };
    
    // Render it
    ReactDOM.render(
      <Example title="The goal is to have the input automatically focused" />,
      document.getElementById("react")
    );
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
    <div id="react"></div>

    你去吧,一个更快、更简单、更容易理解的实现,专注于负载输入。干杯! :)

    【讨论】:

      猜你喜欢
      • 2011-05-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-16
      • 1970-01-01
      • 2018-01-21
      • 2023-03-18
      • 1970-01-01
      相关资源
      最近更新 更多