JavaScript-使用后退按钮关闭弹出窗口

时间:2019-03-24 19:45:50

标签: javascript jquery html html5

我有一个自定义弹出功能。我想要的是使浏览器后退按钮关闭此弹出窗口。

我的理想情况是不要在网址栏中显示井号标签。

我尝试将window.history.pushState('forward', null, '');放入我的showPopup()函数中,然后执行以下操作:

$(window).on('popstate', function () {
    closePopup();
});

这确实有效,但是问题是当我手动关闭弹出窗口时,我必须按两次后退按钮才能导航回到上一页(显然是因为打开弹出窗口时添加了浏览器历史记录条目)。

做到这一点的最佳方法是什么?是否可以在不添加浏览器历史记录条目的情况下完成?本质上,我想做的是复制移动应用程序的行为。在移动应用中按返回按钮通常会关闭所有打开的模式或上下文菜单。

$('.popup-link').click(function() {
    showPopup();
});

$('.popup-close').click(function() {
    hidePopup();
});

function showPopup() {
    $('.popup').addClass('active');
}

function hidePopup() {
    $('.popup').removeClass('active');
}
.popup {
  background-color: #ccc;
  width: 300px;
  height: 300px;
  display: none;
}

.popup.active {
    display: block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button class="popup-link">Click</button>

<div class="popup">
    <button class="popup-close">x</button>
    <!-- popup content here -->
</div>

7 个答案:

答案 0 :(得分:10)

如果不添加浏览器历史记录条目,则无法执行此操作,因为您无法覆盖后退按钮的行为,请参见Intercepting call to the back button in my AJAX application: I don't want it to do anything

Sujumayas答案是一个不错的选择,尽管应该避免打开多个弹出窗口(例如,多次单击按钮时)的历史记录问题,但您应该引入一些其他变量

以下是一些可能的示例代码:

let popupOpen = false;

$(".popup-link").click(function() {
    showPopup();
});

$(".popup-close").click(function() {
    window.history.back();
});

function showPopup() {
    if (popupOpen) {
        window.history.back();
    }
    popupOpen = true;
    window.history.pushState("forward", null, "");
    $(".popup").addClass("active");
}

function hidePopup() {
    popupOpen = false;
    $(".popup").removeClass("active");
}

$(window).on("popstate", function() {
    hidePopup();
});

另外请注意,您可能会遇到Opera Mini的问题:https://caniuse.com/#search=history

答案 1 :(得分:4)

我不建议您覆盖常规的浏览器历史记录管理(后退按钮)以随便使用它。...

我认为您在示例中唯一遗漏的是关闭按钮不应自​​行关闭模式,而应仅执行backbutton事件(最终将关闭模式)。

该简单修复程序将按您希望的方式工作。

答案 2 :(得分:1)

您将有两种选择来实现此目的:

选项1::使用window.beforeunload事件。 reference

$('.popup-link').click(function() {
  showPopup();
  $(window).on("beforeunload", hidePopup);
});

$('.popup-close').click(hidePopup);

function hidePopup() {
  $(window).off("beforeunload", hidePopup);
  $('.popup').removeClass('active');
}

Demo


选项2::使用HTML5历史记录API。 reference

$('.popup-link').click(function() {
  showPopup();
  window.history.pushState('popup-open', null, '');
  $(window).on('popstate', hidePopup);
});

$('.popup-close').click(function() {
  if(history.state == 'popup-open')  {
    window.history.back();
  }
  hidePopup();
});

function hidePopup() {
    $(window).off('popstate', hidePopup);
    $('.popup').removeClass('active');
}

Demo


编辑:sujumayas的想法也很不错。 Demo

此外,我建议仅在必要时注册popstate / beforeunload事件,并在不再需要使用em来避免开销时注销它们。

答案 3 :(得分:0)

我已经在做类似的事情了,它可以很好地与浏览器后退按钮配合使用,也可以通过按下android后退按钮来实现。我也没有在网址栏中显示主题标签。

这是存根(我只是尝试将其应用于您的情况):

function freezeHistory() {
  window.history.pushState({}, window.document.title, window.location.href);
}

function goBack() {
  /*
    Custom history back actions: close panel, close popup, close drop-down menu
  */
  var popupOpen = $(".popup.active").length > 0;
  if(popupOpen) {
    hidePopup();
    return false;
  }
  window.history.back();
  return true;
}

function showPopup() {
  $('.popup').addClass('active');
  freezeHistory();
}

function hidePopup() {
  $('.popup').removeClass('active');
}

$(window).on("popstate", function(e) {
  /* 
     Browsers tend to handle the popstate event differently on page load. 
     Chrome (prior to v34) and Safari always emit a popstate event on page load, 
     but Firefox doesn’t.
  */
  goBack();
})

如果这对于您开箱即用不起作用,是因为恕我直言,您可能需要澄清一点,您希望如何管理页面历史记录。如果您的问题现在没有按您期望的那样进行,请随时为您的问题添加更多细节,但是无论如何,我坚信您已经有了这个主意,并且可以将其应用到您的网络应用场景中。

答案 4 :(得分:0)

打开弹出窗口,然后尝试使用浏览器历史记录按钮来回浏览

$(document).ready(function () {
    // manage popup state
    var poped = false;
    $('.popup-link').click(function () {
        // prevent unwanted state changtes
        if(!poped){
            showPopup();
        }
    });

    $('.popup-close').click(function () {
        // prevent unwanted state changtes
        if(poped){
            hidePopup();
        }
    });

    function showPopup() {
        poped = true;
        $('.popup').addClass('active');
        // push a new state. Also note that this does not trigger onpopstate
        window.history.pushState({'poped': poped}, null, '');
    }

    function hidePopup() {
        poped = false;
        // go back to previous state. Also note that this does not trigger onpopstate
        history.back();
        $('.popup').removeClass('active');
    }
});

// triggers when browser history is changed via browser
window.onpopstate = function(event) {
    // show/hide popup based on poped state
    if(event.state && event.state.poped){
        $('.popup').addClass('active');
    } else {
        $('.popup').removeClass('active');
    }
};
.popup {
            background-color: #ccc;
            width: 300px;
            height: 300px;
            display: none;
        }

        .popup.active {
            display: block;
        }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button class="popup-link">Click</button>

<div class="popup">
    <button class="popup-close">x</button>
    <!-- popup content here -->
</div>

答案 5 :(得分:0)

您可以将window.history.go(-2)添加到popstate。这应该使您返回两次,这将是模式之前的原始页面,因为pushState向您的历史对象添加了一个条目。

相反,您可以使用history.back(2) Use window.location.href to go 2 pages back and reload

答案 6 :(得分:0)

只需运行window.history.back();当关闭弹出窗口时。

$('.popup-close').click(function() {
    hidePopup();
    window.history.back();
});