【问题标题】:Stop propagation for a specific handler停止特定处理程序的传播
【发布时间】:2013-05-31 22:40:45
【问题描述】:

假设我有自定义 dropdown()。单击按钮时,我想调出菜单,而当用户单击菜单外时,我希望它关闭。所以我做了这样的事情:

$(myDropDown).mousedown(dropDownMouseDown);
$("html").mousedown(htmlMouseDown,myDropDown);
function dropDownMouseDown(event) {
    event.target.open();
    event.stopPropagation();//I need this line or else htmlMouseDown will be called immediately causing the dropDown-menu to close right before its opened
}
function htmlMouseDown() {
    this.close();
}

嗯,这行得通。但是,如果我添加其中两个呢?如果我单击打开第一个,那么第二个相同,那么两者都将打开,因为 dropDownMouseDown 停止传播,因此 htmlMouseDown 永远不会被第一个调用。 我该如何解决这个问题? 如果我只有这两个,那么为此添加一些逻辑当然很容易,但是如果数量是动态的?另外我可能不想调用 event.stopPropagation() 因为它会对我正在使用的其他库做一些奇怪的事情来监听那个事件? 我也试过把这条线: $("html").mousedown(htmlMouseDown,myDropDown) 在 dropDownMouseDown-handler 内部,但一旦冒泡到达 html 元素,它就会立即被调用。

【问题讨论】:

  • 您在这里使用事件委托,捕获html 元素上的每个事件。您可以在捕获事件的位置“更具体”(仅在下拉列表本身上),或者 - 如果您想保留事件委托 - 您可以查看事件的 target_of,以查看它是在哪个元素上触发的。

标签: javascript jquery


【解决方案1】:

假设您的 dropdows 有一个选择器(比如说“.dropdown”),我会尝试使用 '.not()'

$('.dropdown').mousedown(dropDownMouseDown);

$("html").on('mousedown', htmlMouseDown);

function dropDownMouseDown(event) {
    event.target.open();
}

function htmlMouseDown(event) {
  $('.dropdown').not($(event.target)).close();
}

这是与 css 类相同的想法: http://jsfiddle.net/eFEL6/4/

【讨论】:

  • 如果我使用 reactjs (this.refs.el != e.target)
【解决方案2】:

如何使用包含最后打开的变量的变量?可能还有很多其他方法可以做到这一点,但这是我能想到的一种方法:

var lastOpened = null; // initially nothing is open (unless something is)

然后:

function dropDownMouseDown(event) {
    if (lastOpened != null) { // if one is still open
        lastOpened.close(); // close it
        lastOpened = null; // nothing is open anymore
    }

    event.target.open();
    lastOpened = event.target; // now this one is open
    event.stopPropagation();
}

function htmlMouseDown() {
    this.close();
    lastOpened = null; // nothing is open
}

这应该以这样一种方式工作,即最后打开的一个总是在打开一个新的之前自行关闭。

【讨论】:

    【解决方案3】:

    感谢您的回答。他们真的很感激。我确实想出了一种让我满意的方法。方法如下:

    $(myDropDown).mousedown(dropDownMouseDown);
    $("html").mousedown(myDropDown,htmlMouseDown);//Pass in the dropDown as the data argument, which can then be accessed by doing event.data in the handler
    function dropDownMouseDown(event) {
        event.target.open();
    }
    function htmlMouseDown(event) {
        if (event.target!=event.data)//event.target is the element that was clicked, event.data is set to the dropdown that this handler was added for. Unless these two elements are the same then we can...
            event.data.close();///close the dropdown this handler was added for
    }
    

    不敢相信我没有想到这一点。在我的情况下,虽然打开/关闭的元素具有子元素,所以 event.target 可能是子元素之一,而不是处理程序附加到的元素。所以我将我的 html-element-handler 更改为:

        function htmlMouseDown(event) {
           var element=event.target;
            while (element) {
                if (element==event.data)
                    return;
                element=element.parentElement;
            }
            event.data.hide();
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-05-06
      • 2019-07-08
      • 1970-01-01
      • 2013-04-24
      • 1970-01-01
      • 2019-01-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多