React触发键盘事件

4
我有一个 PIN 码字段组件,它只是一组被包裹在React.Fragment中的输入框。每次按键时,它会将焦点转移到下一个输入框。当我到达最后一个输入框时,我想触发一个制表符,以将焦点转移到组件外的下一个控件(例如输入框、按钮、链接等)。我尝试分派一个KeyboardEvent,但没有起作用:
const evt = new KeyboardEvent("keydown", {
  ...
  code: "Tab",
  key: "Tab",
})

lastInput.dispatchEvent(evt)

有什么想法吗?

源代码: https://github.com/soywod/react-pin-field
演示地址: https://react-pin-field.soywod.me/

8个回答

6
根据这个答案,浏览器的安全模型会阻止您模拟按下Tab键的操作。
作为替代方案,您可以向组件添加nextFocusId属性,并使用document.getElementById().focus()来移动光标。

1
这是我保留的解决方案。我的组件 PinField 有一个 onComplete 属性。我使用 const nextField = useRef() 保存下一个控制器的引用,并设置 onComplete 如下:onComplete={() => nextField.current && nextField.current.focus()} - soywod

0

我猜这个方法可以解决你的问题 - 当组件重新渲染时,在焦点组件之外触发输入元素的鼠标点击事件。


我会尝试并观察它的行为。 - soywod
请确保在重新渲染完成后触发点击事件,我曾经遇到过同样的问题,后来发现是由于重新渲染引起的。您可以使用状态来查找何时聚焦,或者使用ComponentDidUpdate方法。 - Vivian

0

假设这里有三个主要组件,一个是PIN,另一个是Next,还有一个父组件Parent持有PIN和Next。

  1. Parent传递了一个名为onLast的prop给PIN,当最后一个输入到达时,PIN执行onLast函数。
  2. Parent将一个ref转发给Next,Next将该ref附加到其可聚焦元素(输入、按钮、链接等)上。

在考虑以上条件的基础上,现在我们可以通过条件来“触发”对Next的聚焦。例如,当调用onLast时(即在PIN中达到最后一个输入),使用传统的dom API。

https://developer.mozilla.org/en-US/docs/Web/API/HTMLOrForeignElement/focus

顺便提一下,通过编程触发键盘事件是可以的,这将会触发相应的事件处理程序被执行。但是仅此而已,你不应该期望它能够做更多的事情,比如生成文本、移动焦点(Tab键),这些完全是用户操作,编程无法达到。


0

您可以使用父组件作为中介来帮助子组件彼此通信,就像我下面草拟的示例一样: 在此输入链接描述


0

您可以使用父组件作为中介来帮助子组件相互通信,就像我下面草拟的示例一样,与您所做的完全相同: 示例


0
想了一下,如果您不能做 tab 键,那么可以考虑在当前元素上设置 data-focused 属性,然后在页面上收集所有的输入元素,通过数据属性找到当前聚焦的元素,如果不是最后一个元素,则将焦点移到下一个项。
const inputs = document.querySelectorAll("button, input, select, textarea")
const len = inputs.length - 1  // ignore last item in array
let i = 0

while( i < len ){
  if (inputs[i++].dataSet.focused) {
    inputs[i].focus()
    break
  }
}

0

为最后一个输入定义 keypress 事件的监听器

private onLastInputChange = e => {
    const target = e.target;
    const keyboardEvent = new KeyboardEvent("keypress", {
        bubbles : true,
        cancelable : true,
        key : "Tab",
        shiftKey : false,
        keyCode : 13
    });
    target.dispatchEvent(keyboardEvent);
}

keyCode 13代表制表符ASCII码。

在你的渲染方法中:

<>
   ...
   <input .../>
   <input ... onChange={this.onLastInputChange} />    //<---- the last pin input
</>

-3

你可以尝试在你的元素上使用tabindex


它与问题有什么关联? - soywod

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接