为什么我在文本区域上收到带有"paste"事件的重复文本?



<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<form>
<textarea id="source" cols="100" rows="20"></textarea>
</form>
<script type="text/javascript">
var txarea = document.getElementById('source');
txarea.addEventListener('paste', function(){
let text = txarea.value;
console.log(text);
let replace_text = text.replace(/n/g, ' ')
console.log(replace_text);
txarea.value = replace_text;
});
</script>
</body>
</html>

复制一些带有换行符的文本n,例如

abc
ef

然后重复:Control + A+Control + V.然后你可以看到每次都有越来越多的文本出现。

我试图添加一个debugger并检查发生了什么。但是在我step over最后一句话之后,它就变得一团糟。

怎么了?

让我们分解测试用例以及它如何与您的代码交互。

  1. 用户选择文本区域中的所有文本。
  2. 用户启动"粘贴"。
  3. 在粘贴发生之前,会触发回调。
  4. 您的回调会将文本区域的内容替换为新的修改内容。(用空格替换换行符。
  5. 由于您已将文本区域的内容完全替换为新内容,因此用户的初始文本选择不再有效。因此,有效光标位置现在位于新的替换内容的末尾。
  6. 粘贴发生,将新文本添加到文本区域内容的末尾。

在步骤 #5 中,如果未修改文本(即它没有换行符(,则选择仍然有效,并且粘贴作为替换而不是追加发生。


我认为您要做的是:

  1. 检测用户是否正在尝试粘贴某些文本。
  2. 在粘贴文本之前对其进行修改。(用空格替换换行符。

您可以使用 paste 事件找出正在粘贴的文本,即:

let paste = (event.clipboardData || window.clipboardData).getData('text');

但是,您不想只用粘贴的信息替换文本区域的内容,也不想将其附加到末尾。如果用户将插入符号放在文本中间,然后按 ctrl+v 键,该怎么办?

输入document.execCommand

var txarea = document.getElementById('source');
txarea.addEventListener('paste', function(e) {
e.preventDefault();
let text = '';
if (e.clipboardData || e.originalEvent.clipboardData) {
text = (e.originalEvent || e).clipboardData.getData('text/plain');
} else if (window.clipboardData) {
text = window.clipboardData.getData('Text');
}
console.log(text);
let replace_text = text.replace(/n/g, ' ');
console.log(replace_text);
if (document.queryCommandSupported('insertText')) {
document.execCommand('insertText', false, replace_text);
} else {
document.execCommand('paste', false, replace_text);
}
});
<form>
<textarea id="source" cols="100" rows="20"></textarea>
</form>


注意:Firefox 不支持(在撰写本文时(在textareainput上"insertText"或"paste"命令(错误报告1220696(,但它确实支持在contenteditablediv 上使用这些命令。

最新更新