关于输入问题的 textarea

Mir*_*ror 4 javascript jquery events textarea

我有一个文本区域,我想在其中捕获来自键盘或鼠标/编辑菜单的必要事件。现在,当用户复制通过 CTRL-V 将文本粘贴到 textarea 中时,processUserInput 被调用两次,在keydownpaste上调用两次,由于各种原因这是不受欢迎的。

我以这种方式“解决”了它:

var IsProcessingEvent = false;

$("#textarea").on('click keydown cut paste', processUserInput);

function processUserInput(e) {
    if(!IsProcessingEvent) {
        IsProcessingEvent = true;
        // do the actual processing of user input
        IsProcessingEvent = false;
    }
}
Run Code Online (Sandbox Code Playgroud)

我想知道这个问题是否有更优雅的解决方案。

ps 需要 onpaste 事件,因为用户可以通过鼠标右键单击或通过浏览器编辑菜单复制粘贴文本。

提前致谢!

Gab*_*rtz 5

你做对了伙计。如果您更改keydownfor 会更好keypress,但是如果您愿意,您可以使代码时尚:

var isProcessingEvent = false;

$("#textarea").on('click keypress cut paste', processUserInput);

function processUserInput(e) {
    // Is processing event, so stop here.
    if(isProcessingEvent) {
        return;
    }
    isProcessingEvent = true;

    // do the actual processing of user input

    isProcessingEvent = false;
}
Run Code Online (Sandbox Code Playgroud)

但是,如果我愿意,我将使用 apromisses来处理您对用户输入的处理,这样您就无法在等待过程时冻结所有 UI 线程。

将是这样的:

$("#textarea").on('click keypress cut paste', processUserInput);

function processUserInput(e) {
    // Is processing event, so stop here.
    if(processUserInput.working) {
        // The user trigger the event while it was processing
        processUserInput.doAgain = {
            // save context
            ctx: this, 
            // save event
            e: e 
        };
        return;
    }
    processUserInput.working = true;

    function finished() {
        processUserInput.working = false;

        // The process finished but has new changes in the textfield so...
        var lastEvent = processUserInput.doAgain;
        if (lastEvent) {
            processUserInput.doAgain = null;

            // Process this guy again
            setTimeout(processUserInput.bind(lastEvent.ctx), 0, lastEvent.e);
        }
    }

    function theProcess(e, cb) {

        // do my async stuff here

        // Unfreeze the click/keydown/cut/past events in the textarea
        if (typeof cb === 'function') {
            cb();
        }
    }

    setTimeout(theProcess.bind(this), 0, e, finished);
}
Run Code Online (Sandbox Code Playgroud)

这是异步的示例,但您可以使用异步 ajax 或 web-worker 来处理您的事件,这样您就不会冻结 UI 线程。

PS.:超时不会阻止 UI 线程冻结,它只会将您的进程放在执行队列的末尾。

啊,另一个提示!

如果您正在处理在textarea的文字,是更好的,那么你使用keypress代替keydown,因为如果你在该keydown textarea的价值不会有变化,但按键将获得价值由你按下键改变。

http://www.quirksmode.org/dom/events/keys.html

当然,如果您仍然想使用 keydown,您可以使用setTimeout我在示例中所做的延迟处理。