繁体   English   中英

如何在激活 CSS ":hover" 的纯 JavaScript 中模拟鼠标悬停?

[英]How do I simulate a mouseover in pure JavaScript that activates the CSS ":hover"?

我一直在尝试在 Chrome 中找到模拟mouseover的代码,但即使“鼠标悬停”侦听器被触发,CSS“悬停”声明也永远不会设置!

我也尝试过:

//Called within mouseover listener
theElement.classList.add("hover");

但是似乎没有任何东西可以将元素更改为其hover声明中声明的内容。

这可能吗?

你不能。 这不是可信事件

由用户代理生成的事件,无论是作为用户交互的结果,还是作为对 DOM 更改的直接结果,都被用户代理信任,其特权是脚本通过 DocumentEvent.createEvent 生成的事件所没有的("Event") 方法,使用 Event.initEvent() 方法修改,或通过 EventTarget.dispatchEvent() 方法调度。 可信事件的 isTrusted 属性值为 true,而非可信事件的 isTrusted 属性值为 false。

大多数不受信任的事件不应触发默认操作,但单击或 DOMActivate 事件除外。

您必须添加一个类并在鼠标悬停/鼠标移出事件上手动添加/删除它。

您可以像这样模拟鼠标悬停事件:

HTML

<div id="name">My Name</div>

JavaScript

var element = document.getElementById('name');
element.addEventListener('mouseover', function() {
  console.log('Event triggered');
});

var event = new MouseEvent('mouseover', {
  'view': window,
  'bubbles': true,
  'cancelable': true
});

element.dispatchEvent(event);

背景

我在尝试编写自动化测试时偶然发现了这个问题,以验证给定页面上的特定元素集是否都接收了由 css 为悬停事件设置的一些 css 属性集。

虽然上面的答案完美地解释了为什么不能简单地通过 JS 触发悬停事件然后探测一些感兴趣的 css 值,但它确实回答了最初的问题“我如何在纯 JavaScript 中模拟鼠标悬停来激活 CSS” :徘徊”?” 只是部分。

免责声明

这不是一个高性能的解决方案。 我们仅将它用于自动化测试,其中性能不是问题。

解决方案

simulateCssEvent = function(type){
    var id = 'simulatedStyle';

    var generateEvent = function(selector){
        var style = "";
        for (var i in document.styleSheets) {
            var rules = document.styleSheets[i].cssRules;
            for (var r in rules) {
                if(rules[r].cssText && rules[r].selectorText){
                    if(rules[r].selectorText.indexOf(selector) > -1){
                        var regex = new RegExp(selector,"g")
                        var text = rules[r].cssText.replace(regex,"");
                        style += text+"\n";
                    }
                }
            }
        }
        $("head").append("<style id="+id+">"+style+"</style>");
    };

    var stopEvent = function(){
        $("#"+id).remove();
    };

    switch(type) {
        case "hover":
            return generateEvent(":hover");
        case "stop":
            return stopEvent();
    }
}

解释

generateEvent 读取所有 css 文件,将 :hover 替换为空字符串并应用它。 这具有应用所有 :hover 样式的效果。 现在,您可以通过停止模拟来探索一种咆哮的风格并设置回初始状态。

为什么我们通过从工作表中获取 ,然后执行 element.css(...) 来对整个文档应用悬停效果,而不仅仅是对感兴趣的元素应用?

这样做后,样式将被内联应用,这将覆盖其他样式,这些样式可能不会被原始 css 悬停样式覆盖。

我现在如何模拟单个元素的悬停?

这不是高性能的,所以最好不要。 如果必须,您可以使用 element.is(selectorOfInterest) 检查样式是否适用于您的元素并且仅使用这些样式。

例子

在 Jasmine 中,您现在可以执行:

describe("Simulate CSS Event", function() {
    it("Simulate Link Hover", function () {
      expect($("a").css("text-decoration")).toBe("none");
      simulateCssEvent('hover');
      expect($("a").css("text-decoration")).toBe("underline");
      simulateCssEvent('stop');
      expect($("a").css("text-decoration")).toBe("none");
    });
});

在这种情况下,我通常做的是使用 javascript 添加一个类……并将与:hover相同的CSS附加到这个类

尝试使用

theElement.addEventListener('onmouseover', 
    function(){ theElement.className += ' hovered' });

或者对于较旧的浏览器:

theElement.onmouseover = function(){theElement.className += ' hovered'};

当您离开元素时,您当然必须使用onmouseout删除“悬停”类......

您可以使用pseudo:styler ,这是一个可以将 CSS 伪类应用于元素的库。

(async () => {
  let styler = new PseudoStyler();
  await styler.loadDocumentStyles();
  document.getElementById('button').addEventListener('click', () => {
    const element = document.getElementById('test')
    styler.toggleStyle(element, ':hover');
  })
})();

免责声明:我是这个库的合著者。 我们将其设计为额外支持跨源样式表,特别是在 Chrome 扩展程序中使用,您可能无法控制页面的 CSS 规则。

我假设您想在 dom 操作之后检查 CSS,但是一旦您将鼠标移回 devtools,该事件就不再在该 html 元素上处于活动状态。 您可能希望在 devtools 中为您的 javascript 事件提供类似 :hover 选项的东西。 那不存在,但您可以模拟它。

  1. 打开您的开发工具并单击它以使其处于活动状态。
  2. 在您感兴趣的元素上触发事件。
  3. 在不移动鼠标的情况下,使用 ctrl + shift + p 打开 devtools 命令面板,然后使用键盘选择“禁用 javascript”。

由于 javascript 被禁用,它没有机会再次修改元素。 您可以转到 devtools 并检查 css 和 html,就像您悬停、单击或使用它做其他事情一样。 完成后,再次转到命令面板并选择“启用 javascript”。

SCSS

.hover {
    @extend :hover;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM