【问题标题】:React how to use refs to focus/blur?React 如何使用 refs 来聚焦/模糊?
【发布时间】:2021-06-14 11:52:50
【问题描述】:

我正在阅读来自 Reactjs.org 的 React 文档,但它似乎不适用于我想做的事情。

我想渲染一个带有嵌套 div 的组件。单击每个嵌套的 div 后,它会变成一个输入。在特定 div 之外单击时,它会将输入转换回 div。

我想使用带有模糊/焦点的参考来实现这一点,但我似乎无法弄清楚如何让它工作。

这是我的组件到目前为止的样子,它是一个子组件:

constructor(props) {
    super(props);
    this.textInput = React.createRef();
}
focusRef = () => {
    this.textInput.current.focus();
}
focusEvent = () => {
    console.log("focus event.");
}
render() {
    let item = <div
        className="item-class"
        ref={this.textInput}
        onFocus={this.showIt}
        onClick={this.focusRef}>Item Name</div>
    return(<div>{item}</div>)
}

查看react.js.org提供的示例代码,我很奇怪为什么没有onFocus事件。这不是必需的吗?当元素获得焦点时,还会如何触发事件?在我的代码中,focusRef 被触发但focusEvent 没有被触发,这也是我想不通的。其次,如何检测模糊/失去焦点,以便将输入交换回 div?最后,我对在 div 和 input 之间交换元素的焦点/模糊事件如何与渲染一起工作感到困惑,每次发生这种交换时我不需要重新渲染,也就是每次元素接收/失去焦点时都需要重新渲染吗?这不需要在渲染之间保持元素的焦点(或缺乏焦点)吗?

如果可能,我更喜欢不涉及挂钩的解决方案。

【问题讨论】:

  • 关注input 而不是div。尝试将 div 更改为 input

标签: javascript html reactjs


【解决方案1】:

为了使div 元素具有焦点,它需要可交互。为 div 添加标签索引,以便获得焦点。

function App() {
  return (
    <div className="App">
      <div 
        tabIndex={0} 
        onFocus={() => console.log('focus')} 
        onBlur={() => console.log('blur')}
      >
        Click or tab to me!
      </div>
    </div>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  rootElement
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.13.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.1/umd/react-dom.production.min.js"></script>
<div id="root"></div>

这是一个可切换/可聚焦的 div/输入。它使用状态来保存是否应呈现 div 或输入,并使用 ref 和 componentDidUpdate 方法在切换视图后重新聚焦输入。

class App extends React.Component {
  textInputRef = React.createRef();

  state = {
    isInput: false,
    value: "test"
  };

  componentDidUpdate() {
    const { isInput } = this.state;
    isInput && this.textInputRef.current.focus();
  }

  handleFocus = () => {
    console.log("focus");
    this.setState({ isInput: true });
  };

  handleBlur = () => {
    console.log("blur");
    this.setState({ isInput: false });
  };

  handleChange = (e) => this.setState({ value: e.target.value });

  render() {
    const { isInput, value } = this.state;
    return (
      <div className="App">
        {isInput ? (
          <input
            type="text"
            ref={this.textInputRef}
            value={value}
            onBlur={this.handleBlur}
            onChange={this.handleChange}
          />
        ) : (
          <div tabIndex={0} onFocus={this.handleFocus}>
            {value}
          </div>
        )}
      </div>
    );
  }
}

const rootElement = document.getElementById("root");
ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  rootElement
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.13.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.1/umd/react-dom.production.min.js"></script>
<div id="root"></div>

【讨论】:

  • 我明白了,我以前从未听说过标签索引。不管你的例子帮助我理解了一些事情。我会尝试实现类似的东西。
  • @JonathanYap 尽管您应该尝试将您的 SO 帖子限制在一个特定的问题/问题上,但我正在开发一个实现可切换 div/input 的代码框,因为我发现这是一个有趣的想法。跨度>
  • @JonathanYap 用 a 为您所寻求的工作解决方案更新了答案。请检查一下,看看你的想法。
猜你喜欢
  • 2017-07-16
  • 1970-01-01
  • 2018-05-04
  • 1970-01-01
  • 2011-12-04
  • 1970-01-01
  • 2021-11-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多