Turbolinks 使 JavaScript 不触发导致下拉菜单仅在刷新时起作用

Turbolinks making JavaScript not fire causing dropdowns to only work on refresh

我通过 Javascript 添加 CSS class 来触发通知下拉菜单。但是,我确信 Turbolinks 导致它无法正常工作,因为它似乎只在刷新时起作用。

文档的<body>标签中有一个data-turbolinks="true"。如果我将其更改为 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();
    }
});

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

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

When possible, avoid using the turbolinks:load event to add other event listeners directly to elements on the page body. Instead, consider using event delegation to register event listeners once on document or window.

因此,您将事件侦听器添加到文档或 window,然后使用选择器选择它应该 运行 的元素,例如:

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

这意味着只要将 .header-notifications-trigger a 元素添加到页面,就会触发点击事件处理程序。

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

/*--------------------------------------------------*/
/*  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();
    }
});