如何添加带有快捷方式的特殊字符到任何输入?

How to add special character with shortcut to any input?

我有一个应用程序,每次用户按下快捷键时,我都需要添加一个特殊字符、表情符号或类似的东西 Ctrl+D

问题是我正在使用 flux 并且在我的页面上有几个输入,所以当有人将一个字符添加到其中一个输入时,它会调用一个动作,分派到商店,然后他们更新视图。

要添加这个特殊字符,我需要处理 keyEvent 并知道正在使用哪个输入组件来更新商店中的相应属性。

handleShortcut(evt) {
    if (evt.keyCode === ...) {
        MyActions.addSpecialChar();
        evt.preventDefault();
    }
}

这是唯一的方法吗?我知道我可以使用 document.activeElementevt.target 获取输入,但由于输入由存储状态控制,我无法更改它们的值...有什么想法吗?

** 更新 **

为了让事情更清楚...我想让我的应用程序表现得像 "desktop app",无论我在我的应用程序中使用哪个输入,如果我按下组合键,它都会该输入中的一个特殊字符,这意味着它将由 onChange 处理。 (我对 React 或 JS 不是很熟悉,所以可能我问的太多了..)

所以我会在我的高阶组件中有一个 onKeyPress 来处理组合,并在将特殊字符添加到输入的 value 属性后触发活动输入上的 onChange。

我实现它的方法是在每个输入上设置一个 onKeyPress,它将查找组合并发送与我的 onChange 相同的操作,但在文本中使用特殊字符。

<input
    onKeyPress={(evt)=>{
        /* ... Check combination ... */
        let text = _addSpecialChar(evt.target.value);
        MyActions.update(text);
    }}
    onChange={(evt)=>{
        MyActions.update(evt.target.value);
    }}
/>

正如我上面所说,我想处理与 onChange 的组合,作为一个普通字符,所以我不必在每个输入上添加 onKeyPress。这可能吗?

试试这个:

首先像这样定义你的 handleShortCut 函数:

handleShortcut(input, evt) {
    switch(input) {
      case 'mySpecialInput':
        if (evt.keyCode === ...) {
          MyActions.addSpecialChar()
          evt.preventDefault()
        }
        break
      default:
        ...
    }   
}

然后当你定义你的输入时,做这样的事情:

<input type="text" className="input" 
 value={this.state.value} 
 onChange={this.handleShortcut.bind(this, 'mySpecialInput')}/>

现在您可以在该组件的任何位置使用相同的 handleShortcut fn,并且在每次为该输入调用函数 handleShortcut 时设置 onChange 函数以设置您想要传递的第一个值时使用绑定。 'evt' 参数仍然被传递,但现在作为第二个参数。因此,如果您需要 handleShortcut 了解来自两个不同输入的特定输入源,然后以通用方式处理其他所有内容,请执行以下操作:

<input type="text" className="input" 
     value={this.state.value1} 
     onChange={this.handleShortcut.bind(this, 'mySpecialInput', 'value1')}/>
<input type="text" className="input" 
     value={this.state.value2} 
     onChange={this.handleShortcut.bind(this, 'myOtherSpecialInput', 'value2')}/>
<input type="text" className="input" 
     value={this.state.value3} 
     onChange={this.handleShortcut.bind(this, '', 'value3')}/>

并使您的 handleShortcut 函数看起来像这样:

handleShortcut(input, value, evt) {
    switch(input) {
      case 'mySpecialInput':
        if (evt.keyCode === ...) {
          MyActions.addSpecialChar()
          evt.preventDefault()
        }
        break
      case 'myOtherSpecialInput':
        ...
      default:
        evt.preventDefault()
        this.setState({[value]: this.state.value + 'my default symbol'})
    }   
}

请注意,这次我传递了另一个名为 value 的参数,这是您本地状态中用作 "value" 输入的 属性 的名称。对于每种情况,我们可以硬编码我们想要影响的值,但我们需要 "default" 一般情况的信息。

啊谢谢,你的更新让事情更清楚了。输入表情符号后,您可以尝试在输入上手动触发更改事件吗?

handleShortcut(evt) {
    if (evt.keyCode === ...) {
        MyActions.addSpecialChar();
        evt.preventDefault();
        // Manually trigger on change here of the active element
        evt.target.onchange();
    }
}

如果需要模拟全变事件,可以试试这个:

// Create a new 'change' event
var event = new Event('change');

// Dispatch it.
evt.target.dispatchEvent(event);

感谢@chase 的回答!

我会把我如何解决我的问题的代码放在一起,以供将来参考。

handleShortcut(evt) {
    if (evt.keyCode === ...) {
        this.addSpecialChar(evt);
        let newEvt = new Event('input', {bubbles: true});
        evt.target.dispatchEvent(newEvt);
        evt.preventDefault();
    }
}

addSpecialChar(evt) {
    let curText = evt.target.value;
    let curPos = evt.target.selectionStart;
    let newText = /* Add special char where you want */
    let newPos = curPos + 1; /* Move cursor where you want */
    evt.target.value = newText;
    evt.target.selectionStart = newPos;
}

我的带有助焊剂的组件如下所示:

<HighOrderComponent onKeyPress={this.handleShortcut}>
    <input
        value={this.state.inputVal}
        onChange={
            (evt) => MyAction.updateInputVal(evt.target.value)
        }
    />
    .
    .
    .
    /* Other inputs */
    .
    .
    .
</HighOrderComponent>