使用jQuery的event.preventDefault()和on('input')事件

11

我正在使用$('selector').on('input', function(event) { ... }); 捕捉粘贴事件。

然后,我尝试测试已经粘贴的内容,如果未通过验证,则使用event.preventDefault()取消粘贴。不幸的是,在监听器函数执行时,文本已经被粘贴了,event.preventDefault() 无效。

那么有没有好的方法来捕捉粘贴事件,并且如果粘贴的内容无效,则撤消/防止粘贴呢?

我知道可以使用.on('paste', function(event) { ... }),但这不会给我已经粘贴的文本或粘贴后输入元素的内容,除非我使用setTimeout() 等待一段时间,但我想避免使用setTimeout()


你能创建一个 jsFiddle 的示例吗? - j08691
event.preventDefault() 阻止默认操作,当绑定到 input 事件时,它并不真正阻止您在输入框中键入或粘贴任何内容。当缓存从粘贴的内容中获取值时,您必须将其推迟以获取值,但不需要等待 "一些分钟",将超时设置为零,它仍然可以工作。 - adeneo
我想如果将输入值的捕获和验证的超时设置为100毫秒而不是一分钟,那么这应该是可以的。 - SRy
你只需要像这样做FIDDLE就可以了? - adeneo
@adeneo 我不愿使用setTimeout的原因是,据我所知,操作系统进程调度程序可能会以这样的方式给予进程优先级,即setTimeout函数可能在输入元素更新为已粘贴内容之前执行。虽然,我意识到我可能完全错了... - Val Schuman
4个回答

2
首先,关于元素的事件触发顺序,这里提供一些背景信息:
keydown -> keypress -> paste -> input -> keyup -> change 每当调用preventDefault时,它都会停止链式反应,就好像什么也没有发生过一样。
因此,我的建议是捕获粘贴事件,阻止其默认行为,并在那里执行你的逻辑。
引用块中写道:
我知道我可以使用.on('paste', function(event) { ... }),但那并不能给我粘贴的文本或粘贴后输入元素的内容。
实际上,你可以检索剪贴板的内容。请参见doc。支持所有主流浏览器(但仅限IE11+)。我不知道在问题提出时是否已经有了这个功能。 Fiddle example
$('#myInput').on('paste', function(e) {
    // Cancel the event - this prevents the text from being entered into the input and stops the event chain
    e.preventDefault();

    // Get the content of the clipboard
    let paste = (event.clipboardData || window.clipboardData).getData('text');

    // Validate what it is pasted       
    if (paste == "text to paste") {
        // If condition is satisfied manually set the value of the input
        $(this)
            .val(paste)
            // Manually trigger events if you want
            .trigger('input')
            .trigger('change');
    }
});

代码注释:
  • 此解决方案不包括setTimeout。每当使用setTimeout时,您会看到文本被粘贴的时间非常短,就像闪烁效果。
  • 如果文本符合条件,则手动在input中设置它。但是,这不会触发inputchange事件。如果需要它们,请手动触发它们。
  • 类似的方法是先检查文本,如果不满足要求,则调用preventDefault,否则不做任何操作。这样可以避免手动在输入框中设置值,并在之后触发事件。

即使事件顺序正确,当输入框失去焦点时(即 blur 之前),'change' 事件也只会冒泡。另外请注意,preventDefault 不会停止事件链 - 如果你的意思是防止事件冒泡,你还需要调用 stopPropagation。(参见 https://www.w3schools.com/jsref/event_preventdefault.asp) - L. Monty
我认为onpaste是实验性的,在Chrome 86中,你似乎无法从事件对象中检索输入数据。 - oldboy

0
尝试使用jQuery的.change事件。
如果值不满足您的条件,请将其设置为空白。

change-event 会非常晚地冒泡(只有在输入框失去焦点后才会冒泡)。 - L. Monty

0

使用

$('selector').on('input', function(event) { ... }); 

如果验证未通过,对我来说删除已粘贴的文本似乎是可行的。

遗憾的是,访问剪贴板存在一些缺陷(浏览器会询问是否允许检查剪贴板,跨浏览器兼容性等)。

如果您愿意保存输入的最后一个值,已粘贴的文本仍然可以被计算

这是我计算已粘贴文本的方法:

https://jsfiddle.net/f710o9qd/2/

希望这能对你有所帮助 :)

(如果你发现任何缺陷,请随意优化粘贴文本的计算)


小提琴在输入文本时也会应用验证,而不仅仅是粘贴。我希望这正是您想要的。 - L. Monty

-1

从问题中我理解的是,我们必须在特定验证通过之前不允许将任何数据粘贴到文本框中。我们可以使用on('input')监听器捕获用户输入任何内容时的值,并根据特定条件对其进行验证,如果验证失败,则清空文本框的值,而不是使用event.preventDefault()

(如果我们仍然需要使用on('input')事件监听器,则可以使用此解决方法)

示例代码(我使用console.log()打印粘贴的值):

HTML

<input type='text' id="selector" />

JS:

$(document).ready(function() {
 $('#selector').on('input', function (e){
        if(e.target.value !== "myValue"){
        $('#selector').val('');
    }
    else{
        console.log(e.target.value);
    }
 });
});

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