【问题标题】:multiple simultaneous events javascript多个同时发生的事件javascript
【发布时间】:2017-08-29 00:17:33
【问题描述】:

这可能是一个愚蠢的问题。我知道我有点绿。 我的任务是修改这个旧系统的导航。有两个导航栏。第二个只有搜索按钮。我被要求删除第二个导航栏,并将其替换为显示搜索功能的下拉菜单。由于该系统的年龄,我限制了我可以更改的内容。我能写的 JS 没有限制。他们在 Adob​​e ColdFusion 系统上运行 jQuery 1.11.1(两个月前他们从 1.3.2 升级)

首先:当目标被点击时,mouseenter和click事件都会触发。 mouseenter 首先触发。这会在敏锐的观众可见的桌面上导致问题,但在移动设备上,这会产生可怕的可用性问题。答:据我了解,鼠标事件不会发生在移动设备上,但会发生在我身上。而B:由于mouseenter事件先运行,所以在click事件处理之前激活closeDropDown函数。在 closeDropDown 运行的情况下,其.on('click', f(...eventstuff...)) 会听到旨在触发 openDropDown 功能的打开点击,因此下拉菜单不会打开。

这里是函数。 console.logs 用于检查什么时候运行。

function openDropDown(){
    $('div.dropdown').parent().on('click.open mouseenter', function(event){

      $subject = $(this).find('.dropdown-menu')
      // console.log(event.type, $subject, "first o");

       if(!$subject.is(":visible")){
          // console.log($subject, 'second o');

          $subject.show()
       }else {
         if(event.type == 'click'){
           // console.log('third o');

            $subject.toggle()
        }
    }

    closeDropDown($subject)
    // console.log('open complete');
 })
}


function closeDropDown($x){
    // console.log('first c');

    $(document).on("click.close",function(e){
        // console.log("second c", e.type, "this type");

        if(!$(e.target).closest(".dropdown-menu").parent().length){
            // console.log("third c");

            if($x.is(":visible")){
              // console.log('forth c');
              $x.hide()
            }
        }

        $(document).off("click.close")
        // console.log('complete close');
    })
}

openDropDown()
onSearchClick()

我已经阅读了一些帖子,希望得到一些帮助(例如 thisthat

总的来说,我知道我需要压缩我的代码。我了解解决此问题的几种方法(添加if(... are we on a mobile device...) 或一些计数器/检查,以防止关闭下拉菜单时 closeDropDown 运行)

我真的很想了解事件侦听器的基本原理,以及为什么一个会先于其他东西运行。

虽然有关如何解决此问题的建议很棒,但我希望了解我做错了什么的基本原理。任何基本的指针都非常有用。

注意:我刚读到这个:.is(':visible') not working。我将在没有 .is('visible') 的情况下重写代码。

其他可能有帮助的事情: 当我的所有 console.log(s) 都处于活动状态时,这是 Chrome 开发工具控制台。 首先,页面加载后点击.... 下拉菜单打开并快速关闭。

第二次点击....

谢谢!感谢您的所有帮助!

【问题讨论】:

    标签: javascript jquery coldfusion


    【解决方案1】:

    这是一个相当广泛的问题。我会尽量简洁。我不认为ColdFusion 应该在此处标记,因为它似乎只与 HTML/CSS/JS 有关。

    配置事件

    首先,我想谈谈您配置脚本的方式。 查看事件处理examples from jquery 可能会对您有所帮助。

    大多数人会创建如下所示的事件。它只是说在单击任何 ID 为“alerter”的文档元素时,运行警报功能。

    // Method 1
    $(document).on(click, "#alerter", function(event){
       alert("Hi!");
    });
    

    // Method 2 
    $(document).on("click", "#alerter", ClickAlerter); 
    
    function ClickAlerter(event) {
        alert("Hi!"); 
    }
    

    这两种方法都完全有效。但是,我的意见是第二种方法更具可读性和可维护性。它将事件委托与逻辑分开。

    对于您的代码,我强烈建议您删除事件分配和逻辑的混合。 (它至少会移除一层嵌套)。

    顺便说一句,您的事件侦听器似乎配置不正确。请参阅the correct syntax 和这个来自 jQuery 的示例。

    $( "#dataTable tbody" ).on( "click", "tr", function() {
        console.log( $( this ).text() );
    });
    

    关于多个事件

    如果您在一个对象上有多个事件监听器,那么它们将按照它们注册的顺序被触发。 This SO question 已经涵盖了这一点并提供了一个示例。

    但是,这并不意味着在鼠标进入之前会发生点击。因为您的鼠标必须逐字输入元素才能单击它,所以 mouseenter 事件将首先被触发。换句话说,在考虑事件的顺序时,您至少有两个因素在起作用。

    1. 浏览器触发事件​​的顺序
    2. 注册顺序

    因此,就其本身而言,实际上并不存在所谓的“同时”事件。当浏览器想要触发事件时触发事件,它们将通过事件并按照您分配的顺序触发匹配项。

    如果您想更改默认事件行为,您始终可以选择preventDefaultstopPropagation 来处理此类事件。这将停止浏览器的默认操作,并防止事件分别冒泡到父元素。

    关于移动鼠标事件

    鼠标事件绝对发生在移动设备上,假设它们不会发生是不安全的。 This article 深入介绍了触发事件的范围。引用:

    "[Y]在设计更高级的触摸交互时必须小心:当用户使用鼠标时,它会通过单击事件进行响应,但是当用户触摸屏幕时,触摸和单击事件都会发生。对于一个单击事件的顺序是:

    touchstart
    touchmove
    touchend
    mouseover
    mousemove
    mousedown
    mouseup
    click
    

    我认为你会从阅读那篇文章中受益。它涵盖了有关移动和非移动环境中事件的常见问题和概念。同样,关于您的情况的相关声明:

    不过,有趣的是,CSS :hover 伪类在某些情况下可以被触摸界面触发——点击一个元素会使其在手指向下时变为 :active,并且它也会获得 :hover 状态。 (对于 Internet Explorer,:hover 仅在用户手指向下时有效 - 其他浏览器保持 :hover 有效,直到下一次点击或鼠标移动。)

    一个例子

    我采用了所有这些概念和made an example on jsFiddle 来向您展示其中的一些实际操作。基本上,我通过侦听touchstart 事件并在这种情况下以不同方式处理click 来检测用户是否正在使用触摸屏。因为我没有你的 HTML,我只好制作一个原始界面。这些是指令:

    1. 我们需要确定用户是否有触摸屏
    2. 当用户悬停在按钮上时,应该会出现菜单
    3. 在移动设备上,当用户点击按钮时,菜单应该会出现
    4. 当用户点击按钮外部时,我们需要关闭菜单
    5. 离开按钮应关闭菜单(移动或其他)

    如您所见,我在一个地方创建了所有活动:

    $(document).on("mouseover", "#open", $app.mouseOver);
    $(document).on("mouseout", "#open", $app.mouseOut);
    $(document).on("click", "#open", $app.click);
    $(document).on("touchstart", $app.handleTouch);
    $(document).on("touchstart", "#open", $app.click);
    

    我还创建了一个对象来包装所有逻辑,$app,这为我们提供了更大的灵活性和可读性。这是它的一个片段:

    var $app = $app || {}; 
    $app = {
    
      hasTouchScreen: false,
    
      handleTouch:function(e){
        // fires on the touchstart event
        $app.hasTouchScreen = true;
        $("#hasTouchScreen").html("true");
        $(document).off("touchstart", $app.handleTouch);     
      }, 
    
      click: function(e) {
        // fires when a click event occurrs on the button
        if ($app.hasTouchScreen) {
            e.stopPropagation();
            e.preventDefault();
            return;
        }
    
        // since we don't have a touchscreen, close on click.
        $app.toggleMenu(true);
      }, 
    
      touch: function(e) {
       // fires when a touchstart event occurs on the button
        if ($("#menu").hasClass("showing")) {
           $app.toggleMenu(true);
        } else {
           $app.toggleMenu();
        }    
      } 
    
    };
    

    【讨论】:

      猜你喜欢
      • 2019-10-15
      • 2016-05-08
      • 1970-01-01
      • 1970-01-01
      • 2017-05-12
      • 1970-01-01
      • 2016-12-11
      • 2016-10-19
      • 1970-01-01
      相关资源
      最近更新 更多