Прекратить стрельбу по всплытию на хэне

Я работаю с API истории и использую push и pop state. Я хочу остановить событие popstate от стрельбы в каком-то сценарии, где я только добавляю хэш в URL. например, в некоторых случаях при щелчке на якоре он добавляет # к URL-адресу, а popstate сразу же запускается). Я хочу избежать всех сценариев, в которых # или #somehasvalue добавляется к URL-адресу и останавливает popstate от обстрела. Я поддерживаю URL-адрес с параметрами запроса, и у меня нет сценария, в котором мне нужно событие popstate для запуска с # в URL-адресе.

Вот мой код.

if (supportsHistoryApi()) {

    window.onpopstate = function (event) {
    var d = event.state || {state_param1: param1, state_param2: param2};                       
    var pathName = window.location.pathname,
        params   = window.location.search;

    loadData(event, pathName + params, d.state_param1, d.state_param2);

}

Ответ 1

Насколько я понял, вы не можете остановить показ попугаев, к сожалению.

Что вы можете сделать, это проверить объект event.state. Это будет недействительным при изменении хеша. Поэтому я предлагаю добавить

if(event.state === null) {
   event.preventDefault();
   return false;
}

Для вашего обработчика события popstate в самом начале. Я думаю, что лучший способ предотвратить запуск popstate обработки кода на вашей стороне, когда хеш изменяется, но мне было бы интересно узнать, есть ли другие решения.

Ответ 2

На случай, если кому-то все еще нужно это:

var is_hashed = false;

$(window).on('hashchange', function() {
    is_hashed = true;
});

window.addEventListener('popstate', function(e){
    // if hashchange
    if (is_hashed) {
        e.preventDefault();
        // reset
        is_hashed = false;
        return false;
    }

    // Your code to handle popstate here
    ..................
});

Ответ 3

Это довольно просто.

Чтобы предотвратить popstate события popstate после щелчка по ссылке с хэш-кодом, необходимо исключить необходимость нажатия на ссылку, которая является добавлением хеша в адресную строку браузера.

По сути, вам нужно создать обработчик для события click, проверить, является ли щелчок на элементе, который вы хотите, чтобы предотвратить появление хеша в URL и предотвратить появление хеша, вызвав event.preventDefault(); в обработчике.

Вот пример кода:

/**
 * This your existing 'onpopstate' handler.
 */
window.onpopstate = function(e) {
    // You could want to prevent defaut behaviour for 'popstate' event too.
    // e.preventDefault(); 
    // Your logic here to do things. 

    // The following reload is just an example of what you could want to make
    // in this event handler.
    window.location.reload();
};

/**
 * This is the 'click' event handler that conditionally prevents the default
 * click behaviour.
 */
document.addEventListener('click', function(e) {
    // Here you check if the clicked element is that special link of yours.
    if (e.target.tagName === "A" && e.target.hash.indexOf('#the-link-i-want-make-discernable') > -1) {
        // The 'e.preventDefault()' is what prevent the hash to be added to
        // the URL and therefore prevents your 'popstate' handler to fire.
        e.preventDefault();
        processMySpecialLink(e, e.target);
    }

});

/**
 * Just an example of the link click processor in case you want making something
 * more on the link click (e.g. smooth scroll to the hash).
 */
function processMySpecialLink(e, target) {
    // Make things here you want at user clicking your discernable link.
}

Вот соответствующая разметка HTML:

<!-- Somewhere in the markup -->
<span id="the-link-i-want-make-discernable"></span>
<!-- Some markup -->
<a href="#the-link-i-want-make-discernable">My Special Link</a>
<!-- Another markup -->
<a href="#just-common-link">Any other link</a>

Все это делает то, что описано выше: предотвращает поведение по умолчанию для специальной хэш-ссылки. В качестве побочного эффекта не popstate событие popstate как к URL-адресу не добавляется хэш для особого случая нажатия #the-link-i-want-make-discernable хеша #the-link-i-want-make-discernable.