通过元素的属性检测元素的属性更改-JavaScript

时间:2018-07-05 18:06:04

标签: javascript html attributes

我想知道是否有可能通过元素的属性检测对元素进行的属性更改。

例如,我们可以通过使用HTMLElement.prototype对象及其继承的原型来向元素添加可继承的属性和方法,例如:

// Add our global property
HTMLElement.prototype.sandwich = 'double-decker variety';

// Get the <body> element
let body = document.body;
body.sandwich // => 'double-decker variety'

那么,有没有办法将其扩展到元素属性?

还是应该改为使用Attr.prototype对象?

// Add our global property
Object.defineProperty(HTMLElement.prototype, 'burger', {
    ...,
    set: function changeBurger(newValue) {
        // Our response
        console.log(`Response: You changed our '${oldValue}' burger to a '${newValue}'`)
    }
});

// Get the <body> element
let body = document.body;

// Response: You changed our 'king-sized' burger to a 'family pack'
body.burger = 'family pack';

// Response: You changed our 'family pack' burger to a 'kids delight'
body.setAttribute('burger', 'kids delight');

上面的示例也应该适用于DOM或当前文档中没有的元素,即:从HTMLElement构造函数初始化的对象。

抱歉,这个问题似乎有点含糊,我希望我给出的示例能够阐明问题的主题。

感谢任何愿意花时间回答的人。

1 个答案:

答案 0 :(得分:3)

正确的方法扩展HTMLElement的方法是使用CustomElements, 有一个名为attributeChangedCallback的生命周期回调。

然后,当使用objectName.setAttribute('attrName','attrValue')设置属性时 该函数被调用。

您还可以将 MutationObserverconfig={attributes:true}一起使用(请小心使用,错误的实现会严重影响性能)。

另一种实现方法是编写一个读取所有属性并将其转换为setter / getters的函数……类似

    class WatchableObject{
            constructor(){
                this.handler = ()=>{};
            }
            watch(handler){
                if(!this.beingWatched()) {
                    delete this.handler;

                    let properties = Object.getOwnPropertyNames(this);
                    properties.forEach((prop) => {
                        if (this.hasOwnProperty(prop)) {
                            Object.defineProperty(this, prop, {
                                set: (newValue) => {
                                    let oldValue = this["_" + prop];
                                    this["_" + prop] = newValue;
                                    this.handler.call(this,oldValue,newValue);
                                },
                                get: () => {
                                    return this["_" + prop];
                                }
                            });
                        }
                    });
                }
                this.handler = handler;
            }
            unwatch(){
                this.watch(()=>{});
            }
            beingWatched(){
                return (this.handler.toString() != "()=>{}");
            }
    }

    let a = new WatchableObject();
    a.b = "hello";
    a.c = "daniel";
    a.watch(()=>{alert("a change has been made.")});
    a.b = "bye";
    a.unwatch();
    a.b = "hello again";