我正在开发一个需要将文本插入contenteditable="true" div(准确地说是基于Draftjs的文本字段)的应用程序。

现在,我知道Draft.js使用react了,应该以这种方式使用它,但是在这种情况下,该应用程序已经存在,并且这是与之配合使用的第三方 Electron 应用程序。

我正在macOS上进行在线通知回复,因此我需要将该回复文本粘贴到draftJS字段中,但是,当我使用以下方式时:

document.querySelector('div[contenteditable="true"]').focus();
document.execCommand('insertText', false, 'message');

它抛出一个错误:
javascript - 使document.execCommand ('insertText',false, 'message')与draftjs一起工作?-LMLPHP

我能够使用以下方法使其工作:

const event = document.createEvent('TextEvent');
event.initTextEvent('textInput', true, true, window, 'message', 0, locale);

但是此API已被弃用,如果消息中包含表情符号,则该API无法正常工作。

有没有办法做到这一点而不会导致错误呢?
我发现应该替换initTextEvent的新API只是new Event()(请参阅docs),但是我无法确定它是否支持textInput事件。

要使用它,您可以转到https://draftjs.org/并在chrome开发工具中使用它。

我真的很感谢这里的帮助,因为我不知道该怎么做才能使其正常工作。另外,我知道人们是jquery的狂热者,但我更喜欢 native js解决方案(尽管欢迎使用任何解决方案)。

编辑:

请注意:
我没有使用react,我想修改的输入字段(draftjs)正在使用react,我想使用本地js将文本输入其中。

编辑2:

对于遇到此问题的其他人,我想在Facebook Messenger文本字段(使用Draftjs)中插入文本。

我设法找到一种可行的解决方法。
它确实使用了已弃用的API(event.initTextEvent),但这是我发现即使对emoji表情也有效的唯一方法。 如果您有更好的解决方案,请发布答案。
它的工作方式如下:
async function sendReply(message: string): Promise<void> {
       const inputField = document.querySelector('[contenteditable="true"]') as HTMLElement;
       if (inputField) {
               const previousMessage = inputField.textContent;
               // Send message
               inputField.focus();
               await insertMessageText(message, inputField);
               (await elementReady('._30yy._38lh._39bl')).click();
               // Restore (possible) previous message
               if (previousMessage) {
                       insertMessageText(previousMessage, inputField);
               }
       }
}

function insertMessageText(text: string, inputField: HTMLElement): void {
       // Workaround: insert placeholder value to get execCommand working
       if (!inputField.textContent) {
               const event = document.createEvent('TextEvent');
               event.initTextEvent('textInput', true, true, window, '_', 0, '');
               inputField.dispatchEvent(event);
       }

       document.execCommand('selectAll', false, undefined);
       document.execCommand('insertText', false, text);
}

这是 typescript 代码,因此您可能需要将其更改为使用js。

通过使用event.initTextEvent在textField内插入一个占位符值,然后将该文本替换为:
document.execCommand('selectAll', false, undefined);
document.execCommand('insertText', false, 'text');

已在Chrome中测试:版本71.0.3578.98

最佳答案

尽管很久以前就问过这个问题,并且@JoniVR找到了解决方法,但这可能会对其他人有所帮助。
在进行扩展时,我也遇到了类似的问题。我还尝试了方法document.execCommand('insertText',false,text)。它在LinkedIn上有效,但在Facebook上无效。它在错误的节点中插入了文本。尽管document.execCommand API在某些地方可用,但现在已经过时了。
对于使用drafjs编辑器的Facebook和其他任何网站,我们需要使用dataTransferclipBoardEvent API调度一次粘贴事件,以使draftjs认为已粘贴文本并进行相应处理。

const dataTransfer = new DataTransfer();

function dispatchPaste(target, text) {
  // this may be 'text/html' if it's required
  dataTransfer.setData('text/plain', text);

  target.dispatchEvent(
    new ClipboardEvent('paste', {
      clipboardData: dataTransfer,

      // need these for the event to reach Draft paste handler
      bubbles: true,
      cancelable: true
    })
  );

  // clear DataTransfer Data
  dataTransfer.clearData();
}
如果需要更多信息,请选中此link

10-07 13:39