我想知道是否有可能通过元素的属性检测对元素进行的属性更改。
例如,我们可以通过使用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
构造函数初始化的对象。
抱歉,这个问题似乎有点含糊,我希望我给出的示例能够阐明问题的主题。
感谢任何愿意花时间回答的人。
答案 0 :(得分:3)
正确的方法扩展HTMLElement的方法是使用CustomElements,
有一个名为attributeChangedCallback
的生命周期回调。
然后,当使用objectName.setAttribute('attrName','attrValue')设置属性时 该函数被调用。
您还可以将 MutationObserver与config={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";