在 DOM 元素的样式对象更改后,您可以使用 javascript 钩子触发器吗?

Posted

技术标签:

【中文标题】在 DOM 元素的样式对象更改后,您可以使用 javascript 钩子触发器吗?【英文标题】:Can you have a javascript hook trigger after a DOM element's style object changes? 【发布时间】:2012-06-07 17:55:38 【问题描述】:

一个元素有一个 javascript style 对象,其中包含不同的 css 样式名称和值。我想在每次该对象更改不使用轮询时触发一个函数。有没有办法以跨浏览器兼容的方式做到这一点,并且可以与第三方代码可靠地工作(因为假设您提供了一个插入式脚本)?绑定像 DOMAttrModifiedDOMSubtreeModified 这样的 javascript 事件是不够的,因为它们在 Chrome 中不起作用。

【问题讨论】:

***.com/questions/4561845/… 我有一个答案,但是,您是针对古代浏览器吗?还是主要浏览器? @3p3r 我也针对旧版本的浏览器,但我肯定会对只针对新版本的解决方案感兴趣 @3p3r 但是不,我不关心没有人使用的旧浏览器,例如 Konqueror 或其他... @user730569 我有already answered,使用gettersetter 以获得最佳性能 【参考方案1】:

即使对于所有最现代的浏览器,也没有跨浏览器的方式来实现这一点。您必须通过一个可以触发事件侦听器的函数来路由您的所有 css 样式更改。这将是最干净的方法。

【讨论】:

【参考方案2】:

编辑 4: 现场演示

$(function() 
  $('#toggleColor').on('click', function() 
    $(this).toggleClass('darkblue');
  ).attrchange(
    trackValues: true,
    callback: function(event) 
      $(this).html("<ul><li><span>Attribute Name: </span>" + event.attributeName + "</li><li><span>Old Value: </span>" + event.oldValue + "</li><li><span>New Value: </span>" + event.newValue + "</li></ul>");
    
  );
);
body 
  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
  font-size: 12px;

#toggleColor 
  height: 70px;
  width: 300px;
  padding: 5px;
  border: 1px solid #c2c2c2;
  background-color: #DBEAF9;

#toggleColor span 
  font-weight: bold;

#toggleColor.darkblue 
  background-color: #1A9ADA;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="http://meetselva.github.io/attrchange/javascripts/attrchange.js"></script>
<p>Click below div to toggle class darkblue.</p>
<div id="toggleColor"></div>

编辑 3: 我将所有这些放在一起作为一个插件,可以从 git attrchange 下载,这里是 demo page

编辑 2:

    修复了 IE7 和 IE8 中的属性名称

编辑 1:

    处理多个元素 将条件排序为 MutationObserver、DOMAttrModified 和 onpropertychange,以便更好地实施。 在回调中添加了修改后的属性名称。

感谢@benvie 的反馈。

演示: http://jsfiddle.net/zFVyv/10/(在 FF 12、Chrome 19 和 IE 7 中测试。)

$(function() 
    (function($) 
        var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver;

        function isDOMAttrModifiedSupported() 
            var p = document.createElement('p');
            var flag = false;

            if (p.addEventListener) p.addEventListener('DOMAttrModified', function() 
                flag = true
            , false);
            else if (p.attachEvent) p.attachEvent('onDOMAttrModified', function() 
                flag = true
            );
            else return false;

            p.setAttribute('id', 'target');

            return flag;
        

        $.fn.attrchange = function(callback) 
            if (MutationObserver) 
                var options = 
                    subtree: false,
                    attributes: true
                ;

                var observer = new MutationObserver(function(mutations) 
                    mutations.forEach(function(e) 
                        callback.call(e.target, e.attributeName);
                    );
                );

                return this.each(function() 
                    observer.observe(this, options);
                );

             else if (isDOMAttrModifiedSupported()) 
                return this.on('DOMAttrModified', function(e) 
                    callback.call(this, e.attrName);
                );
             else if ('onpropertychange' in document.body) 
                return this.on('propertychange', function(e) 
                    callback.call(this, window.event.propertyName);
                );
            
        
    )(jQuery);

    $('.test').attrchange(function(attrName) 
        alert('Attribute: ' + attrName + ' modified ');
    ).css('height', 100);

);

参考:

    Detect if DOMAttrModified supported DOMAttrModified for chrome Mutation Observer Why should we avoid using Mutation events? onPropertyChange IE

Mutation Observers 是 DOM4 中突变事件的提议替代品。预计它们将包含在 Firefox 14 和 Chrome 18 中

浏览器支持:

onpropertychange - 在 IE 中受支持(在 IE 7 中测试)

DOMAttrModified - 在 IE 9、FF 和 Opera 中受支持

MutationObservers - 非常新,在Chrome 18 中运行良好。不确定它支持多远,尚未在 Safari 中进行测试。

感谢 @benvie 添加有关 WebkitMutationObserver 的信息

【讨论】:

谢谢! WebkitMutationObservers 的浏览器支持怎么样? (它在 chrome 和 safari 中可以追溯到多远?)onPropertyChange 呢? MutationObservers 是非常新的,但在最近的 WebKit 和 Firefox 中得到支持。不过,它们是 DOM 修改事件的未来,我很高兴看到它们包含在这个答案中。 ++这个答案 哦,如果它也处理无前缀版本(Firefox 15 支持)会更好。 var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver. @benvie 我在哪里可以找到支持它们的特定浏览器版本? isDOMAttrModifiedSupported 中不需要 attachEvent 分支:DOM 突变事件支持与 IE 中的 addEventListener 支持一致(两者都在 IE 9 中引入)。【参考方案3】:

EDIT2:

如果您仍想使用mutation observer,请使用此库:mutation-summary


编辑:

正如我在下面的回答中所说,并感谢 Vega 的评论,不建议在大型应用程序中使用诸如 object.watchmutation observers 之类的东西。这是来自MDN的实际报价:

通常你应该避免使用watch()unwatch() 可能的。这两种方法仅在 Gecko 中实现,它们是 主要用于调试用途。此外,使用观察点 对性能有严重的负面影响,尤其如此 用于全局对象,例如窗口。你通常可以使用 settersgetters代理。有关详细信息,请参阅兼容性。

警告

因此,如果您的检查清单中有跨浏览器兼容性,我再次强烈建议覆盖style 对象的setters 和getters。


使用object.watch 并牢记这些跨浏览器解决方案: Javascript Object.Watch for all browsers? object.watch polyfill Watch for object properties changes in JavaScript

您也可以覆盖元素的style 对象的gettersetter 方法。

有一个可用的 jQuery 插件,jQuery watch

【讨论】:

我认为 watch 使用轮询.. 并且 OP 正在寻找 不使用轮询的对象更改 @Vega 好吧,我不太了解 Gecko 的源代码,但我认为“轮询”OP 意味着手动 setIntervals,不是吗?【参考方案4】:

在对similar question 的答复中,有人建议如果您知道样式设置交互将通过标准接口(即始终 使用 jQuery 等)执行,则建议:每当调用库方法时都会触发自定义事件。

这将允许更广泛的支持矩阵,但如果在不使用库方法的情况下执行任何属性更改,则会忽略任何属性更改。似乎这种方法不适用于native setters,因为它们不能总是被依赖。

【讨论】:

【参考方案5】:

我发现这个小插件可以做到这一点,并且可以更改它以添加您希望的任何突变...甚至 scrollHeight 更改侦听器。

插件:http://www.jqui.net/jquery-projects/jquery-mutate-official/

这里是演示: http://www.jqui.net/demo/mutate/

【讨论】:

这个插件使用了一种有趣的方法,但它确实使用了轮询(请参阅setTimeout(reset, mutate.speed); 行(您可能需要取消缩小它以使其可读)。【参考方案6】:

您可以使用attrchange jQuery plugin。该插件的主要功能是绑定一个HTML元素属性变化的监听函数。

【讨论】:

这就是 Vega 的回答 (***.com/a/11004907/971299) 实际上插件是因为这个问题而写的!

以上是关于在 DOM 元素的样式对象更改后,您可以使用 javascript 钩子触发器吗?的主要内容,如果未能解决你的问题,请参考以下文章

Vue获取DOM元素样式 && 样式更改

查找正在更改 DOM 元素的 javascript

jQuery基础(样式篇,DOM对象,选择器,属性样式)

在 CSS 悬停事件中,我可以更改另一个 div 的样式吗? [复制]

chrome扩展跟踪前端JavaScript,该JavaScript使用DOM/jQueryAPI在运行时操作html-DOM元素(例如,更改样式、附加事件侦听器)。

jQuery--样式