Turbolink使JavaScript不触发,导致下拉列表仅在刷新时起作用

时间:2018-08-12 10:13:15

标签: javascript laravel laravel-5 turbolinks

我有一个通过Javascript添加CSS类而触发的通知下拉菜单。但是,我确信Turbolinks导致它无法正常工作,因为它似乎只能在刷新时工作。

文档的data-turbolinks="true"标记中有一个<body>。如果将其更改为false,则可以正常运行。

如果我将data-turbolinks="false"放在特定链接的<div>标记中,它仍然无法正常工作。

所以我想我将不得不更改JaveScript,以使其不受Turbolinks的影响。但是,我不确定该如何处理。这是针对Laravel 5.6应用的。

/*--------------------------------------------------*/
/*  Notification Dropdowns
/*--------------------------------------------------*/
$(".header-notifications").each(function() {
    var userMenu = $(this);
    var userMenuTrigger = $(this).find('.header-notifications-trigger a');

    $(userMenuTrigger).on('click', function(event) {
        event.preventDefault();

        if ( $(this).closest(".header-notifications").is(".active") ) {
            close_user_dropdown();
        } else {
            close_user_dropdown();
            userMenu.addClass('active');
        }
    });
});

// Closing function
function close_user_dropdown() {
    $('.header-notifications').removeClass("active");
}

// Closes notification dropdown on click outside the conatainer
var mouse_is_inside = false;

$( ".header-notifications" ).on( "mouseenter", function() {
  mouse_is_inside=true;
});
$( ".header-notifications" ).on( "mouseleave", function() {
  mouse_is_inside=false;
});

$("body").mouseup(function(){
    if(! mouse_is_inside) close_user_dropdown();
});

// Close with ESC
$(document).keyup(function(e) { 
    if (e.keyCode == 27) {
        close_user_dropdown();
    }
});

1 个答案:

答案 0 :(得分:1)

我认为问题在于脚本仅在第一页加载时选择元素,而不是在每次页面加载时选择元素。例如,调用$(".header-notifications")会尝试查找具有.header-notifications类的所有元素,但是此操作仅运行一次,因此,在使用Turbolinks加载新页面时,body会得到替换,并且那些选择的元素不再存在。在加载整个页面之前,不会再次执行脚本,因此该脚本仅运行一次-永远不会重新选择.header-notifications元素。

要解决此问题,Turbolinks自述文件建议使用事件委托:

  

如果可能,请避免使用turbolinks:load事件将其他事件侦听器直接添加到页面正文上的元素。而是考虑使用event delegation在文档或窗口上注册一次事件监听器。

因此,您将事件侦听器添加到文档或窗口中,然后使用选择器选择应在其上运行的元素,例如:

$(document).on(
  "click", ".header-notifications-trigger a", function (event) { … }
)

这意味着每当将.header-notifications-trigger a元素添加到页面时,都会触发click事件处理程序。

考虑到这一点,您可能希望将脚本更新为以下内容:

/*--------------------------------------------------*/
/*  Notification Dropdowns
/*--------------------------------------------------*/

// For convenience and to prevent unnecessary $() calls
var doc = $(document);

doc.on("click", ".header-notifications-trigger a", function (event) {
    event.preventDefault();

    var user_menu = $(this).closest(".header-notifications");

    if (user_menu.is(".active")) {
        close_user_dropdown();
    } else {
        close_user_dropdown();
        user_menu.addClass('active');
    }
});

// Closing function
function close_user_dropdown() {
    $('.header-notifications').removeClass("active");
}

// Closes notification dropdown on click outside the container
var mouse_is_inside = false;

doc.on("mouseenter", ".header-notifications", function() {
    mouse_is_inside = true;
});

doc.on("mouseleave", ".header-notifications", function() {
    mouse_is_inside = false;
});

doc.on("mouseup", function(){
    if(!mouse_is_inside) close_user_dropdown();
});

// Close with ESC
doc.on("keyup", function(e) { 
    if (e.keyCode == 27) {
        close_user_dropdown();
    }
});