只检测伪元素上的点击事件

IT技术 javascript jquery css
2021-01-23 05:37:13

请看这个小提琴:http : //jsfiddle.net/ZWw3Z/5/

我的代码是:

p {
    position: relative;
    background-color: blue;
}

p:before {
    content: '';
    position: absolute;
    left:100%;
    width: 10px;
    height: 100%;
    background-color: red;
}
    <p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate...</p>

我只想在伪元素(红色位)上触发点击事件。也就是说,我不希望在蓝色位上触发点击事件。

6个回答

这不可能; 伪元素根本不是 DOM 的一部分,因此您不能将任何事件直接绑定到它们,只能绑定到它们的父元素。

如果你必须只在红色区域有一个点击处理程序,你必须创建一个子元素,比如 a span,将它放在开始<p>标签之后,将样式应用到p span而不是p:before,并绑定到它。

似乎在现代浏览器pointer-events中,元素本身及其伪元素的不同是可能的jsfiddle.net/ZWw3Z/70
2021-03-16 05:37:13
pointer-events 根据 Ilya 发布的 jsfiddel,似乎对 IE9 不起作用。
2021-03-18 05:37:13
@theyuv 不,在该页面上,链接的左侧和右侧都可以单击整行。只有链接本身具有不同的点击处理程序,因此点击它不会触发折叠/展开子树。
2021-03-22 05:37:13
@user393274:IE9 不支持 SVG 之外的指针事件。
2021-03-28 05:37:13
@Ilya Streltsyn 太棒了——不是“正确”的答案(如果你还需要点击元素就行不通),但对于 div 上的“关闭按钮”效果很好
2021-04-08 05:37:13

事实上,这是可能的。您可以检查单击的位置是否在元素之外,因为这只会在单击::before或被::after单击时发生

此示例仅检查右侧的元素,但这应该适用于您的情况。

span = document.querySelector('span');

span.addEventListener('click', function (e) {
    if (e.offsetX > span.offsetWidth) {
        span.className = 'c2';
    } else {
        span.className = 'c1';
    }
});
div { margin: 20px; }
span:after { content: 'AFTER'; position: absolute; }

span.c1 { background: yellow; }
span.c2:after { background: yellow; }
<div><span>ELEMENT</span></div>

JSFiddle

对于火狐:jsfiddle.net/wC2p7/16如果使用嵌套元素,您可能需要根据需要计算嵌套偏移量(例如 jQuery: $(e.target).offset().left )
2021-03-15 05:37:13
很棒的人,谢谢,它有效。但是在 Firefox 和其他符合标准的浏览器中,为了测试鼠标是否悬停,:after您必须检查,if (e.clientX > span.offsetLeft + span.offsetHeight)因为这些浏览器没有该e.offsetX属性。小提琴:jsfiddle.net/Noitidart/wC2p7/18
2021-03-18 05:37:13
如果::before::after位于元素内部,这实际上将不起作用
2021-03-19 05:37:13
如果 jQuery 决定支持,那就更酷了,$('a:after').on('click', fn)但我真的没有看到这种情况发生:p
2021-03-26 05:37:13
它对我不起作用,当我点击其中一个时,文本会突出显示。使用 Firefox,如果重要(不应该)。
2021-04-03 05:37:13

现代浏览器上,您可以尝试使用 pointer-events css 属性(但它会导致无法检测父节点上的鼠标事件):

p {
    position: relative;
    background-color: blue;
    color:#ffffff;
    padding:0px 10px;
    pointer-events:none;
}
p::before {
    content: attr(data-before);
    margin-left:-10px;
    margin-right:10px;
    position: relative;
    background-color: red;
    padding:0px 10px;
    pointer-events:auto;
}

当事件目标是您的“p”元素时,您就知道它是您的“p:before”。

如果您仍然需要检测主 p 上的鼠标事件,您可以考虑修改您的 HTML 结构的可能性。您可以添加span标签和以下样式:

p span {
    background:#393;
    padding:0px 10px;
    pointer-events:auto;
}

事件目标现在既是“span”又是“p:before”元素。

没有 jquery 的例子:http : //jsfiddle.net/2nsptvcu/

jquery 示例:http : //jsfiddle.net/0vygmnnb/

以下是支持指针事件的浏览器列表:http : //caniuse.com/#feat=pointer-events

我不知道为什么是父节点。你是说如果我点击 .box:before 之类的事件,那么 .box 无法检测到任何点击?
2021-03-21 05:37:13
这部分是正确的:如果您的 CSS 包含类似 .box{pointer-events:none;} .box:before{pointer-events:auto;} 的内容,那么唯一仍然支持事件的元素是 p:before。无论如何请记住,js 会返回主 .box 元素,因为 .box:before 并不真正存在于 DOM 中。
2021-04-09 05:37:13
您实际上仍然可以检测原始元素上的鼠标事件。你不需要总是设置这个规则,你可以简单地设置时间来检查元素是否仍然悬停,即使只有它的伪元素接收指针事件:jsfiddle.net/0z8p5ret这将导致大量回流,所以任何其他方式可能会更好。
2021-04-10 05:37:13

简答:

我做的。我为那里的所有小人物写了一个动态使用的函数......

显示在页面上的工作示例

登录到控制台的工作示例

长答案:

……还是做了。

我花了一段时间才这样做,因为页面上并没有真正的伪元素。虽然上面的一些答案在某些情况下有效,但它们都不能既是动态的,也不能在元素的大小和位置都出乎意料的情况下工作(例如绝对定位元素覆盖父元素的一部分)。我的没有。

用法:

//some element selector and a click event...plain js works here too
$("div").click(function() {
    //returns an object {before: true/false, after: true/false}
    psuedoClick(this);

    //returns true/false
    psuedoClick(this).before;

    //returns true/false
    psuedoClick(this).after;

});

怎么运行的:

它抓取父元素的高度、宽度、顶部和左侧位置(基于远离窗口边缘的位置)并抓取高度、宽度、顶部和左侧位置(基于父容器的边缘) ) 并比较这些值以确定伪元素在屏幕上的位置。

然后比较鼠标的位置。只要鼠标在新创建的变量范围内,它就会返回 true。

笔记:

使父元素相对定位是明智的。如果你有一个绝对定位的伪元素,这个函数只有在它基于父元素的尺寸定位时才有效(所以父元素必须是相对的......也许粘性或固定也可以工作......我不知道)。

代码:

function psuedoClick(parentElem) {

    var beforeClicked,
      afterClicked;

  var parentLeft = parseInt(parentElem.getBoundingClientRect().left, 10),
      parentTop = parseInt(parentElem.getBoundingClientRect().top, 10);

  var parentWidth = parseInt(window.getComputedStyle(parentElem).width, 10),
      parentHeight = parseInt(window.getComputedStyle(parentElem).height, 10);

  var before = window.getComputedStyle(parentElem, ':before');

  var beforeStart = parentLeft + (parseInt(before.getPropertyValue("left"), 10)),
      beforeEnd = beforeStart + parseInt(before.width, 10);

  var beforeYStart = parentTop + (parseInt(before.getPropertyValue("top"), 10)),
      beforeYEnd = beforeYStart + parseInt(before.height, 10);

  var after = window.getComputedStyle(parentElem, ':after');

  var afterStart = parentLeft + (parseInt(after.getPropertyValue("left"), 10)),
      afterEnd = afterStart + parseInt(after.width, 10);

  var afterYStart = parentTop + (parseInt(after.getPropertyValue("top"), 10)),
      afterYEnd = afterYStart + parseInt(after.height, 10);

  var mouseX = event.clientX,
      mouseY = event.clientY;

  beforeClicked = (mouseX >= beforeStart && mouseX <= beforeEnd && mouseY >= beforeYStart && mouseY <= beforeYEnd ? true : false);

  afterClicked = (mouseX >= afterStart && mouseX <= afterEnd && mouseY >= afterYStart && mouseY <= afterYEnd ? true : false);

  return {
    "before" : beforeClicked,
    "after"  : afterClicked

  };      

}

支持:

我不知道......它看起来像 ie 是愚蠢的,有时喜欢将 auto 作为计算值返回。如果尺寸在 CSS 中设置,它似乎在所有浏览器中都能正常工作。所以......在你的伪元素上设置你的高度和宽度,并且只在顶部和左侧移动它们。我建议将它用于您认为它不起作用的事情上。比如动画什么的。Chrome 工作......像往常一样。

psEUdo,不是psUEdo!
2021-03-12 05:37:13
我应该提到它在 Firefox 中不起作用,因为没有event定义。不过,它适用于 Chrome 和 Edge。
2021-03-15 05:37:13
@SebastianZartner - 事件是一个关键字。这是用户做某事的时候。我从字面上解释了您的评论上方的这两条评论。当用户与页面交互时,会触发一个事件(在大多数情况下)。事件是来自事件侦听器“.click()”的关键字。如果开发人员想要为事件使用不同的名称,他们可以在事件侦听器中设置它,例如“.click(e)”,这是一种更常见的查看方式。然而......即使我有一个在上面工作的链接,我也会包括一个更明显的并且不登录到控制台而是登录到有需要的页面的链接。
2021-03-22 05:37:13
event每次触发事件时都会通过事件处理函数传递。就像点击或打字一样。当我们使用该.click()函数时,我们正在等待点击事件。我们可以指定并说.click(function(e){...})使事件成为,e但也可以仅使用event.
2021-03-28 05:37:13
上面的代码不起作用,因为event未定义。
2021-03-28 05:37:13

我的答案适用于想要单击页面确定区域的任何人。这对我的绝对定位对我有用 :after

由于这个文章,我才意识到(用jQuery)我可以用e.pageYe.pageX而不必担心e.offsetY/Xe.clientY/X浏览器之间的问题。

通过反复试验,我开始在 jQuery 事件对象中使用 clientX 和 clientY 鼠标坐标。这些坐标为我提供了鼠标相对于浏览器视口左上角的 X 和 Y 偏移量。然而,当我阅读 Karl Swedberg 和 Jonathan Chaffer 的 jQuery 1.4 参考指南时,我看到他们经常提到 pageX 和 pageY 坐标。查看更新的jQuery文档后,我看到这些是jQuery标准化的坐标;而且,我看到他们给了我鼠标相对于整个文档(不仅仅是视口)的 X 和 Y 偏移量。

我喜欢这个event.pageY想法,因为它总是相同的,因为它相对于文档我可以使用 offset() 将它与我的 :after 的父元素进行比较,它返回它的 X 和 Y 也相对于文档。

因此,我可以在整个页面上提出一系列永不改变的“可点击”区域。


这是我在 codepen 上演示


或者如果对 codepen 太懒了,这里是 JS:

* 我只关心我的例子的 Y 值。

var box = $('.box');
// clickable range - never changes
var max = box.offset().top + box.outerHeight();
var min = max - 30; // 30 is the height of the :after

var checkRange = function(y) {
  return (y >= min && y <= max);
}

box.click(function(e){
  if ( checkRange(e.pageY) ) {
    // do click action
    box.toggleClass('toggle');
  }
});