使用 javascript bubbling/capturing 检测中间节点
Detect intermediate node with javascript bubbling/capturing
我需要使用事件委托捕获内部带有图像的锚节点。
document.addEventListener(
'click',
function(event) {
console.log(event.target);
return true;
},
false
);
<a href="#" class="link">
<img src="http://placehold.it/100x100" alt="">
</a>
event.target 总是 img.
如何检查点击是否是在具有 class 的节点上进行的。link?
更新: 这里需要明确的是 an example with jQuery
当我使用 jQuery.on() 时,在回调函数的 this
属性 中有 a
节点,而不是 img
节点。使用纯 JS,我只能确定初始目标。
您可以通过以下调用检查元素是否具有 class:
element.classList.contains('link');
您现在想要的是在单击 <a class="link">
中的 <img>
时执行某些操作。要确定点击的 <img>
是否有父 <a class="link">
,我们必须向上遍历其父树并检查。
这与您的 jQuery 示例非常相似,即
$('body').on('click', '.link', callback)
除了 jQuery 匹配整个查询,而不仅仅是 class。
以下是您可以执行此操作的方法:
// function to determine if the element has the link class
const hasLinkClass = element => element
? element.classList && element.classList.contains('link')
: false;
// function that accepts an event handler and returns
// a wrapper function arround it.
// The wrapper is called it if the passed in event
// object contains as its target an <img> with a parent
// with .link class
function filterImagesWithinLinks(handler) {
return function(event) {
let elem = event.target;
// ignore clicks that are not on an image (it might be better to be more specific here)
if (elem.tagName === 'IMG') {
// filter until we find the parent with .link class
while (elem && !hasLinkClass(elem)) {
elem = elem.parentNode;
}
// if a parent with .link class was found,
// call the original handler and set its `this`
// to the parent.
if (elem) {
handler.call(elem, event);
}
}
};
}
// function handler that fires when
// an <img> that has a parent with
// class 'link' was clicked
function handler(event) {
console.log('target : ', event.target);
console.log('this : ', this);
}
document.addEventListener(
'click',
filterImagesWithinLinks(handler),
false
);
a.link {
display: block;
padding: 10px;
background: #018bbc;
}
.middle {
background: salmon;
padding: 10px;
text-align: center;
}
<a href="#" class="link">
<p class="middle">
<img src="http://placehold.it/100x100" alt="" />
</p>
</a>
如果您在锚标签中添加一些文本或其他内容,将更容易看出 a
和 img
之间的区别。请参阅 JSFiddle 上的这个示例——它显示 class link
的元素是否被单击:
https://jsfiddle.net/Lppt4hyk/4/
这是代码(仅对您的代码稍作修改):
<a href="#" class="link"> Anchor
<img src="http://placehold.it/100x100" alt="">
</a>
document.addEventListener(
'click',
function( event ) {
var patt = /(?:^link | link$|^link$| link )/g;
if (patt.test(event.target.className)) {
alert('link class was clicked');
}
else { alert('link class was not clicked'); }
return true;
},
false
);
div {
background: red;
display: block;
height: 90%;
width: 90%;
}
.n1 {
background: yellow;
}
.n2 {
background: green;
}
更新: 添加了对 link
class 名称的检查,如果它不是分配给该元素的唯一 class。
更新: 添加了正则表达式检查以清除 link
作为较大单词的一部分。
我需要使用事件委托捕获内部带有图像的锚节点。
document.addEventListener(
'click',
function(event) {
console.log(event.target);
return true;
},
false
);
<a href="#" class="link">
<img src="http://placehold.it/100x100" alt="">
</a>
event.target 总是 img.
如何检查点击是否是在具有 class 的节点上进行的。link?
更新: 这里需要明确的是 an example with jQuery
当我使用 jQuery.on() 时,在回调函数的 this
属性 中有 a
节点,而不是 img
节点。使用纯 JS,我只能确定初始目标。
您可以通过以下调用检查元素是否具有 class:
element.classList.contains('link');
您现在想要的是在单击 <a class="link">
中的 <img>
时执行某些操作。要确定点击的 <img>
是否有父 <a class="link">
,我们必须向上遍历其父树并检查。
这与您的 jQuery 示例非常相似,即
$('body').on('click', '.link', callback)
除了 jQuery 匹配整个查询,而不仅仅是 class。
以下是您可以执行此操作的方法:
// function to determine if the element has the link class
const hasLinkClass = element => element
? element.classList && element.classList.contains('link')
: false;
// function that accepts an event handler and returns
// a wrapper function arround it.
// The wrapper is called it if the passed in event
// object contains as its target an <img> with a parent
// with .link class
function filterImagesWithinLinks(handler) {
return function(event) {
let elem = event.target;
// ignore clicks that are not on an image (it might be better to be more specific here)
if (elem.tagName === 'IMG') {
// filter until we find the parent with .link class
while (elem && !hasLinkClass(elem)) {
elem = elem.parentNode;
}
// if a parent with .link class was found,
// call the original handler and set its `this`
// to the parent.
if (elem) {
handler.call(elem, event);
}
}
};
}
// function handler that fires when
// an <img> that has a parent with
// class 'link' was clicked
function handler(event) {
console.log('target : ', event.target);
console.log('this : ', this);
}
document.addEventListener(
'click',
filterImagesWithinLinks(handler),
false
);
a.link {
display: block;
padding: 10px;
background: #018bbc;
}
.middle {
background: salmon;
padding: 10px;
text-align: center;
}
<a href="#" class="link">
<p class="middle">
<img src="http://placehold.it/100x100" alt="" />
</p>
</a>
如果您在锚标签中添加一些文本或其他内容,将更容易看出 a
和 img
之间的区别。请参阅 JSFiddle 上的这个示例——它显示 class link
的元素是否被单击:
https://jsfiddle.net/Lppt4hyk/4/
这是代码(仅对您的代码稍作修改):
<a href="#" class="link"> Anchor
<img src="http://placehold.it/100x100" alt="">
</a>
document.addEventListener(
'click',
function( event ) {
var patt = /(?:^link | link$|^link$| link )/g;
if (patt.test(event.target.className)) {
alert('link class was clicked');
}
else { alert('link class was not clicked'); }
return true;
},
false
);
div {
background: red;
display: block;
height: 90%;
width: 90%;
}
.n1 {
background: yellow;
}
.n2 {
background: green;
}
更新: 添加了对 link
class 名称的检查,如果它不是分配给该元素的唯一 class。
更新: 添加了正则表达式检查以清除 link
作为较大单词的一部分。