Javascript在不滚动的情况下更改window.location.hash,但仍会触发CSS:target伪类

Javascript在不滚动的情况下更改window.location.hash,但仍会触发CSS:target伪类,javascript,html,css,Javascript,Html,Css,据我所知,有两种方法可以更改URL末尾的哈希值窗口.location.hash和历史记录.pushState。但是,history.pushState,所以这就结束了 演示一种在不滚动的情况下修改location.hash的方法,但此解决方法无法在具有匹配ID的元素上触发:target伪类 下面是一个简单的例子。两个链接按预期工作::target被触发并显示选项卡,但必要时也会滚动到视图中。两个链接不起作用::未触发目标,但阻止滚动 (函数(){ 函数setHash(事件){ event.pr

据我所知,有两种方法可以更改URL末尾的哈希值<代码>窗口.location.hash和
历史记录.pushState
。但是,
history.pushState
,所以这就结束了

演示一种在不滚动的情况下修改
location.hash
的方法,但此解决方法无法在具有匹配ID的元素上触发
:target
伪类

下面是一个简单的例子。两个链接按预期工作:
:target
被触发并显示选项卡,但必要时也会滚动到视图中。两个链接不起作用:
:未触发目标,但阻止滚动

(函数(){
函数setHash(事件){
event.preventDefault();
var decoy=document.querySelector(“.dummy tabpanel”);
var tabId=event.currentTarget.getAttribute('href');
变量id=tabId.replace(/^#/,“”);
var tabPanel=document.getElementById(id);
decoy.style.top=document.body.scrollTop+'px';
tabPanel.setAttribute('id','');
诱饵.setAttribute('id',id);
window.location.hash=tabId;
decoy.setAttribute('id','');
tabPanel.setAttribute('id',id);
返回false;
}
函数setHashDirect(事件){
event.preventDefault();
var tabId=event.currentTarget.getAttribute('href');
window.location.hash=tabId;
返回false;
}
var tabLinks=document.querySelectorAll('a[href^=“#”]”);
for(tabLink的var tabLink){
tabLink.addEventListener(“单击”,tabLink.classList.contains('direct')?SetHashDirect:setHash);
}
})()
.tabs{
页边空白顶部:300px;//尝试使滚动成为必要
}
.tabs[role=“tabpanel”]{
显示:无;
}
.tabs[role=“tabpanel”]:目标{
显示:块;
}
.虚拟选项卡面板{
位置:绝对位置;
可见性:隐藏;
}

这是第一个选项卡(不会显示) 这是两个选项卡(不会显示) 这是第三个选项卡(应显示) 这是第四个选项卡(应显示)
实际上,
历史记录。pushState
可能应该更新CSS
:target
选择器,因为在使用
历史记录后,使用浏览器的后退和前进按钮来来回导航。pushState
确实会更新它。它已经存在,而不是当前的不一致行为。如果他们选择让它更新CSS,那么您的代码将按原样工作。如果他们选择不更新CSS,那么浏览器将不得不更改后退和前进按钮的行为,以不更新由
history.pushState
,或可能的任何按钮创建的条目的CSS,这看起来显然是一个错误的举动

因此,您的代码将来可能可以正常工作,但从现在起,您必须通过调用
history.pushState
来解决这个问题,然后为用户来回导航。以下是一个基于以下方面的解决方案:

函数pushHashAndFixTargetSelector(哈希){
history.pushState({},document.title,hash);//按正常方式调用
const onpopstate=window.onpopstate;//存储旧的事件处理程序以在以后还原它
window.onpopstate=function(){//调用history.back()时将调用此函数
window.onpopstate=onpopstate;//还原原始处理程序
history.forward();//再次前进以更新CSS
};
history.back();//返回以触发上述函数
}

从理论上讲,即使在他们标准化了预期的行为之后,这种解决方法仍将继续发挥作用。

您始终可以向每个元素添加一个类或ID,并在其上使用css。换句话说,您希望通过
:target
,通过链接显示隐藏的内容,但是您不想跳转到
:target
目的地?@zer00ne,这是完全正确的,但我希望避免添加和删除类或修改内联样式