【问题标题】:Trying to dispatch keypress event in React尝试在 React 中调度按键事件
【发布时间】:2020-08-07 22:00:11
【问题描述】:

我有一个带有输入元素的组件,我想在该输入元素上触发一个“tab”按键事件,以便在发生特定逻辑集时跳转到下一个输入元素。

我在第一个输入元素上有一个引用,我正在尝试像这样触发按键事件:

useEffect(() => {
  if (ref.current) {
    ref.current.focus();
    setTimeout(() => {
      ref.current.dispatchEvent(
        new KeyboardEvent("keypress", { key: "Tab" })
      );
    }, 3000);
  }
});

首先我确保用.focus() 选择第一个输入元素,然后在 3 秒后触发按 Tab 键,希望看到焦点移动到下一个字段,但它似乎不起作用。

这似乎是一个奇怪的例子,但这只是一个原型。我实际上打算做的是在我提交第一个输入字段时触发一些代码,这将获取一些带有其他输入字段的行,一旦呈现,我需要触发“tab”键。我想避免将 ref 附加到这些动态加载的输入字段,因为我觉得它会增加很多开销来跟踪 ref 并将它们传递下来,而我所需要的只是利用 tab 顺序并模拟按键以 tab 到加载后的第一个动态加载项。我可以将单个引用添加到您需要提交以填充动态字段的字段。

我注意到一些在线示例直接在 ref 对象上调用 .dispatchEvent(),但是如果我尝试得到一个错误,告诉我该函数不存在,所以我在 current 属性上调用它。不确定这是否有任何相关性。

这是一个原型的链接,上面的代码来自:https://codesandbox.io/s/wizardly-hopper-vrh4w?file=/src/App.js:149-441

【问题讨论】:

标签: javascript reactjs keyevent react-ref


【解决方案1】:

根据我在 cmets 中得到的答案,您似乎无法通过模拟击键来触发本机浏览器行为(作为一项安全功能)(页面下方有 2/3 的注释):https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent

【讨论】:

    【解决方案2】:

    试试这个方法

    new KeyboardEvent("keydown", { keyCode: "Tab", which: 9 })
    

    这是我获得which https://keycode.info/ 的方法

    【讨论】:

    • 你的keyCode不正确,应该也是9keycode 应该是 'Tab'。如果您改用keyjs.dev,则可以使用隐藏功能来复制整个KeyboardEvent 对象:只需打开 DevTools,在控制台中,您将看到所有正在记录的事件,您可以展开要复制的事件。
    【解决方案3】:

    正如@funkylaundry 所指出的,出于安全原因,您不能通过调度自己的事件来触发本机浏览器操作。

    不过,你想做的事情可以通过autofocus (HTML)/autoFocus(JSX)属性来实现,如下图:

    const App = () => {
      const [showExtraFields, setShowExtraFields] = React.useState(false);
      const [showMoreExtraFields, setShowMoreExtraFields] = React.useState(false);
      
      React.useEffect((e) => {
        setTimeout(() => {
          setShowExtraFields(true);
        }, 3000);
        
        setTimeout(() => {
          setShowExtraFields(false);
          setShowMoreExtraFields(true);
        }, 6000);
        
        setTimeout(() => {
          setShowExtraFields(true);
          setShowMoreExtraFields(true);
        }, 9000);
      }, []);
    
      return (
        <form>
          <input placeholder="Input 1" autoFocus />
          
          { showExtraFields && (<React.Fragment>
            <input placeholder="Input 2" autoFocus />
            <input placeholder="Input 3" />
            <input placeholder="Input 4" />
          </React.Fragment>) }
          
          { showMoreExtraFields && (<React.Fragment>
            <input placeholder="Input 5" autoFocus />
            <input placeholder="Input 6" />
            <input placeholder="Input 7" />
          </React.Fragment>) }
        </form>
      );
    }
    
    ReactDOM.render(<App />, document.querySelector('#app'));
    body {
      font-family: monospace;
    }
    
    input {
      display: block;
      margin-bottom: 8px;
      font-family: monospace;
      padding: 8px;
      background: white;
      border: 2px solid black;
    }
    <script src="https://unpkg.com/react@16.7.0-alpha.0/umd/react.development.js"></script>
    <script src="https://unpkg.com/react-dom@16.7.0-alpha.0/umd/react-dom.development.js"></script>
    
    <div id="app"></div>

    注意焦点如何Input 1 -&gt; Input 2 -&gt; Input 5 -&gt; Input 2

    基本上,如果页面上有多个autoFocus 输入,则要挂载的最后一个元素会得到它。这就是为什么在上次更新中,当显示两组输入时,焦点转到刚刚安装的 Input 2,而不是 Input 5,后者位于 Input 2 之后但已经出现在页面上。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-04-07
      • 2011-03-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-10-15
      • 2017-08-23
      • 1970-01-01
      相关资源
      最近更新 更多