简体   繁体   English

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

[英]Can you have a JavaScript hook trigger after a DOM element's style object changes?

An element has a JavaScript style object which contains the different names and values of CSS styles.一个元素有一个 JavaScript style对象,其中包含 CSS 样式的不同名称和值。 I'd like to trigger a function every time this object changes without use of polling .我想在不使用 polling 的情况下每次更改此对象时触发一个函数。 Is there any way to do this in a way that is cross-browser compatible and would work reliably with third party code (because let's say you're providing a drop-in script)?有没有办法以跨浏览器兼容的方式做到这一点,并且可以可靠地与第三方代码一起工作(因为假设您正在提供一个插入式脚本)? Binding a JavaScript event like DOMAttrModified or DOMSubtreeModified won't suffice because they don't work in Chrome.绑定DOMAttrModifiedDOMSubtreeModified类的 JavaScript 事件是不够的,因为它们在 Chrome 中不起作用。

Edit 4: Live Demo编辑 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>

Edit 3: I have put all this together as a plugin that can be downloaded from git attrchange and here is the demo page .编辑 3:我将所有这些放在一起作为一个插件,可以从 git attrchange下载,这里是演示页面

Edit 2:编辑2:

  1. Fix for propertName in IE7 & IE8修复 IE7 和 IE8 中的属性名称

Edit 1:编辑1:

  1. Handle multiple elements处理多个元素
  2. Ordered the conditions as MutationObserver, DOMAttrModified and onpropertychange for better implementation.将条件排序为 MutationObserver、DOMAttrModified 和 onpropertychange 以便更好地实现。
  3. Added modified Attribute Name to the callback.在回调中添加了修改后的属性名称。

Thanks to @benvie for his feedback.感谢@benvie 的反馈。

DEMO: http://jsfiddle.net/zFVyv/10/ (Tested in FF 12, Chrome 19 and IE 7.)演示: 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);

});

Ref:参考:

  1. Detect if DOMAttrModified supported检测是否支持 DOMAttrModified
  2. DOMAttrModified for chrome DOMAttrModified for chrome
  3. Mutation Observer 突变观察者
  4. Why should we avoid using Mutation events?为什么我们应该避免使用 Mutation 事件?
  5. onPropertyChange IE onPropertyChange IE

Mutation Observers is the proposed replacement for mutation events in DOM4. Mutation Observers 是 DOM4 中突变事件的提议替代品。 They are expected to be included in Firefox 14 and Chrome 18预计它们将包含在 Firefox 14 和 Chrome 18 中

Browser Support:浏览器支持:

onpropertychange - is supported in IE (tested in IE 7) onpropertychange - 在 IE 中受支持(在 IE 7 中测试)

DOMAttrModified - is supported in IE 9, FF and Opera DOMAttrModified - 在 IE 9、FF 和 Opera 中受支持

MutationObservers - is very new and it worked fine in Chrome 18 . MutationObservers - 非常新,在Chrome 18中运行良好。 Not sure how far it is supported and yet to be tested in Safari.不确定它支持多远,尚未在 Safari 中进行测试。

Thanks @benvie on adding info about WebkitMutationObserver感谢@benvie添加有关 WebkitMutationObserver 的信息

EDIT2:编辑2:

If you still want to use mutation observer , use this library: mutation-summary如果您仍想使用mutation observer ,请使用此库: mutation-summary


EDIT: 编辑:

As I said in my answer below and thanks to Vega for his comment, using things such as object.watch or mutation observers are not recommended for using in large apps.正如我在下面的回答中所说,并感谢 Vega 的评论,不建议在大型应用程序中使用诸如object.watchmutation observers之类的东西。 this is actual quote from MDN :这是来自MDN的实际报价:

Generally you should avoid using watch() and unwatch() when possible.一般来说,您应该尽可能避免使用watch()unwatch() These two methods are implemented only in Gecko, and they're intended primarily for debugging use.这两种方法仅在 Gecko 中实现,主要用于调试。 In addition, using watchpoints has a serious negative impact on performance, which is especially true when used on global objects , such as window.此外,使用观察点对性能有严重的负面影响,尤其是在全局对象上使用时尤其如此,例如窗口。 You can usually use setters and getters or proxies instead.您通常可以改用settergetter代理 See Compatibility for details.有关详细信息,请参阅兼容性。

Warning警告

So if cross-browser compatibility is in your check list, Again, I highly suggest overriding setter s and getter s of style object.因此,如果您的检查清单中有跨浏览器兼容性,我强烈建议您覆盖style对象的settergetter


use object.watch and have these in mind for a cross-browser solution: 使用object.watch并牢记这些跨浏览器解决方案:

You may override getter and setter methods of element's style object too.您也可以覆盖元素style对象的gettersetter方法。

There is a jQuery plugin available for this, jQuery watch有一个可用的 jQuery 插件, jQuery watch

I have found this little plugin that does exactly that and it can be changed to add any mutation you wish... Even scrollHeight change listener.我发现这个小插件可以做到这一点,并且可以更改它以添加您希望的任何突变...甚至 scrollHeight 更改侦听器。

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

here is the demo: http://www.jqui.net/demo/mutate/这是演示: http ://www.jqui.net/demo/mutate/

Even for all of the most modern browers there is no cross-browser way to achieve this.即使对于所有最现代的浏览器,也没有跨浏览器的方式来实现这一点。 You would have to route all of your css style changes through a function which could trigger event listeners.您必须通过一个可以触发事件侦听器的函数来路由所有 css 样式更改。 This would be the cleanest method.这将是最干净的方法。

In an answer to a similar question , it was suggested that if you know that style-setting interactions would be performed via a standard interface (ie always using jQuery etc.) it was suggested that custom events be fired whenever the library method is called.在对类似问题的回答中,建议如果您知道样式设置交互将通过标准接口执行(即始终使用 jQuery 等),则建议在调用库方法时触发自定义事件。

This would allow for a broader support matrix but would leave any property change ignored if performed without using the library method.这将允许更广泛的支持矩阵,但如果在不使用库方法的情况下执行任何属性更改,则会忽略任何属性更改。 It also appears that such an approach is not applicable to native setters as they cannot always be relied on.似乎这种方法不适用于本地 setter ,因为它们不能总是被依赖。

You can use attrchange jQuery plugin .您可以使用attrchange jQuery 插件 The main function of the plugin is to bind a listener function on attribute change of HTML elements.该插件的主要功能是绑定一个HTML元素属性变化的监听函数。

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

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