[英]Iterate over all Links in the Dom - Is there a more elegant solution?
我在页面上遍历所有由pushState处理的元素,并防止出现默认行为。 我以为我的函数非常昂贵,所以我尝试了其他与事件监听器不同的解决方案,这些解决方案无法按预期工作。 在该xhr请求的readystate事件发生后,每次单击链接时都会运行此函数。 最后,我要通过xhr更改元素的内容,然后再次运行此函数。
我也尝试这样做: https : //gomakethings.com/why-event-delegation-is-a-better-way-to-listen-for-events-in-vanilla-js/
这会添加一个侦听器,看起来像是您单击的位置,但是最终向我显示了我单击的其他元素,而不是我的a元素,因此这也不起作用。
var dragging = false;
function addPushStateActionToAllLinks() {
var e = Array.from(document.getElementsByTagName("a"));
for ( var i = 0; i < e.length; i++ ) {
e[i].ontouchmove = function () {
dragging = true;
};
e[i].ontouchstart = function () {
dragging = false;
};
e[i].onclick = function ( el ) {
el.preventDefault ? el.preventDefault() : (el.returnValue = false);
};
if(e[i].getAttribute('rel') !== 'noopener noreferrer' && e[i].getAttribute('href') != "" ) {
e[i].ontouchend = function ( el ) {
if ( dragging === true ) {
return;
}
loadInternalLinkByXhr( this, true );
el.preventDefault ? el.preventDefault() : (el.returnValue = false);
};
} else {
e[i].ontouchend = function ( el ) {
if ( dragging === true ) {
return;
}
loadExternalLink( this );
el.preventDefault ? el.preventDefault() : (el.returnValue = false);
};
}
}
}
编辑:我也尝试过,可以按预期工作,但我认为在移动设备上单击速度较慢:
function someFunction( ) {
var e = document.getElementsByTagName("a");
for ( var i = 0; i < e.length; i++ ) {
if(e[i].getAttribute('rel') !== 'noopener noreferrer' && e[i].getAttribute('href') != "" ) {
e[i].onclick = function ( el ) {
if(typeof window.navigator.vibrate !== 'undefined') {
window.navigator.vibrate( 1 );
}
loadInternalLinkByXhr( this, true );
el.preventDefault ? el.preventDefault() : (el.returnValue = false);
};
} else {
e[i].onclick = function ( el ) {
if(typeof window.navigator.vibrate !== 'undefined') {
window.navigator.vibrate( 1 );
}
loadExternalLink( this );
el.preventDefault ? el.preventDefault() : (el.returnValue = false);
};
}
}
}
我想要最高效的最佳做法。 当您单击链接,导航,标题等时,只有我的网站的一部分在改变。保持原样。 我尝试向每个元素添加事件侦听器,最终触发多个xhr请求,而这个请求越来越多,而我无法弄清楚为什么会发生这种情况,我还尝试在添加新事件侦听器之前将其删除,但似乎仍会向其中添加多个它。 对于我来说,这仅适用于完整的页面请求,我想避免这种情况。 但是,我的功能按预期工作,在仅使用onclick之前,现在我尝试在ontouchend上进行移动阻止,因为它可能会更快地做出反应。 该项目是新项目,因此我对现代浏览器功能和Vanilla JS持开放态度。
如果在原始设计中使用函数声明,则可以对每个事件使用一个函数,而不必重复它们。
function ontouchmove () {
dragging = true;
};
function ontouchstart() {
dragging = false;
};
function onclick( el ) {
el.preventDefault ? el.preventDefault() : (el.returnValue = false);
};
for ( var i = 0; i < e.length; i++ ) {
e[i].ontouchmove = ontouchmove;
e[i].ontouchstart ontouchstart;
e[i].onclick = onclick;
if(e[i].getAttribute('rel') !== 'noopener noreferrer' && e[i].getAttribute('href') != "" ) {
e[i].ontouchend = function ( el ) {
if ( dragging === true ) {
return;
}
loadInternalLinkByXhr( this, true );
el.preventDefault ? el.preventDefault() : (el.returnValue = false);
};
} else {
e[i].ontouchend = function ( el ) {
if ( dragging === true ) {
return;
}
loadExternalLink( this );
el.preventDefault ? el.preventDefault() : (el.returnValue = false);
};
}
}
}
否则,使用JQuery一次选择所有元素并在整个选择中设置事件会更有意义。
var allLinks = $('a');
allLinks.on('touchmove', function () {
dragging = true;
};)
allLinks.on('touchstart', function () {
dragging = false;
};)
allLinks.on('cick', function () {
this.preventDefault ? this.preventDefault() : (this.returnValue = false);
};)
您可以使用.each
方法来迭代选择并基于属性执行操作。
allLinks.each(function() {
if ($(this).attr('rel') !== 'noopener noreferrer' && $(this).attr('href') != "" ){
...
}
});
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.