停止在 hashchange 上触发 popstate
Posted
技术标签:
【中文标题】停止在 hashchange 上触发 popstate【英文标题】:stop firing popstate on hashchange 【发布时间】:2014-10-27 08:52:40 【问题描述】:我正在使用 History API 并使用推送和弹出状态。我想阻止 popstate 事件在我只将哈希附加到 URL 的某些情况下触发。例如,在某些情况下,单击锚点会将 #
附加到 URL 并立即触发 popstate)我想避免将 #
或 #somehasvalue
附加到 URL 并阻止 popstate 触发的所有情况。我正在使用查询参数维护 URL,并且我没有任何需要在 URL 中使用#
触发 popstate 事件的情况。
这是我的代码。
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】:据我发现,不幸的是,您无法阻止 popstate 触发。
您可以做的是检查event.state
对象。这将在哈希更改时为空。
所以我建议添加一个
if(event.state === null)
event.preventDefault();
return false;
一开始就发送给您的 popstate 事件处理程序。 我认为这是防止在哈希更改时触发您身边的 popstate 处理代码的最佳方法,但我很想知道是否有其他解决方案。
【讨论】:
这在您返回到您打开的第一页时不起作用。因为那时state
也是null
,但仍然没有hashchange
@HugoDelsing,也许在页面加载时总是replaceState
?
顺便说一句,popState
事件是not cancelable,所以preventDefault
-ing 它什么都不做。在页面加载时检查 null
并结合调用 replaceState
似乎工作正常。【参考方案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
..................
);
【讨论】:
我无法让它工作。使用 Chrome 85。popstate 事件发生在 hashchange 之前【参考方案3】:这很简单。
为了防止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
事件,因为对于单击 #the-link-i-want-make-discernable
哈希链接的特殊情况,不会向 URL 添加哈希。
【讨论】:
【参考方案4】:我有办法!
当调用 popstate 事件时,检查路径名是否已更改,或者只是哈希更改。在下面观看它对我的作用: window.pop_old = document.location.pathname;
window.pop_new = '';
window.onpopstate = function (event)
window.pop_new = document.location.pathname;
if(pop_new != pop_old)
//diferent path: not just the hash has changed
else
//same path: just diferent hash
window.pop_old = pop_new; //save for the next interaction
;
【讨论】:
以上是关于停止在 hashchange 上触发 popstate的主要内容,如果未能解决你的问题,请参考以下文章
hashchange 事件未在 IE10 和 IE11 中触发,具有 history.pushState 和 url 手动操作的组合