为什么焦点处理程序使用错误的参数执行



>我在文本字段上有一个焦点处理程序:

$("#input").on("focus", (e) => {
    // do some stuff
});

但是,当我右键单击时,我不希望执行该焦点处理程序,所以我这样做了:

$("#input").on("mousedown", (e) => {
    if (e.button === 2) { // right click
        e.preventDefault();
    }
});

但是,这也阻止了文本字段在我右键单击时获得焦点。我仍然希望它获得焦点,我只是不希望处理程序执行,所以我手动触发了处理程序:

$("#input").on("mousedown", (e) => {
    if (e.button === 2) { // right click
        e.preventDefault();
        $("#input").trigger("focus", true);
    }
});
$("input").on("focus", (e, someParam) => {
    if (someParam) return;
    // do some stuff
});

这样,文本字段获得焦点,但我们立即从处理程序中返回。

我注意到的问题是,当我第一次触发焦点处理程序时,someParam undefined,我们最终执行do some stuff。对于所有后续右键单击,someParam为 true。

我注释掉了触发焦点处理程序的行,事实上,焦点处理程序永远不会执行,因为我们调用preventDefault,所以似乎处理程序的第一次执行必然来自$("#input").trigger("focus", true);。那么,如果我将true作为额外参数传入,为什么someParam未定义呢?

小提琴。在铬中测试。

这似乎是jQuery的当前问题。请参阅此 github 问题。

作为解决方法,请尝试以下操作:

var a = $("#a");
var _focusData = null;
var focusEvent = (e) => {
    if (_focusData) {
        _focusData = null;
        return;
    }
    _focusData = null;
    var t = $("textarea").first();
    t.val(t.val() + "nfocus");
};
a.on("mousedown", (e) => {
   if (e.button === 2) {
       e.preventDefault();
       var t = $("textarea").first();
       t.val(t.val() + "n" + e.button);
       _focusData = true;
       a.trigger("focus");
   }
});
a.on("focus", focusEvent);

在做了更多的研究之后,包括尝试使用 $.Event 触发自定义事件,似乎最好的做法是使用堆栈跟踪、污染全局范围或降级您的 jQuery 版本。

除了 CBroe 的评论之外,我还找到了另一种解决方案(仅在 else 语句中执行逻辑(:

使用命名函数作为鼠标按下处理程序,然后检查堆栈跟踪。

var a = $("#a");
a.on("mousedown", onMouseDown);
function onMouseDown(e) {
   if (e.button === 2) {
       e.preventDefault();
       e.stopImmediatePropagation()
       var t = $("textarea").first();
       t.val(t.val() + "n" + e.button);
       a.trigger("focus", true);
   }
}
a.on("focus", (e, someParam) => {
    var stackTrace = getStackTrace();
    if(stackTrace.indexOf("onMouseDown") >= 0) return;
    var t = $("textarea").first();
    t.val(t.val() + "nfocus");
    console.log(someParam);
    console.trace();
});
var getStackTrace = function() {
  var obj = {};
  if(Error.captureStackTrace) { //Chrome (IE/Edge? Didn't test)
    Error.captureStackTrace(obj, getStackTrace);
  }
  else { //Firefox
    obj = Error();
  }
  return obj.stack;
};

https://jsfiddle.net/bjj56eua/4/

当我输入这个时,FrankerZ发布了一个看起来更好的答案。我建议这样做。这是一个涉及字符串解析的肮脏黑客,但它有效。这不是一个好主意。

相关内容

最新更新