[英]How could I create an element wrapper in Javascript?
出於純粹的教育和好奇心目的,我正在嘗試創建一個元素包裝器 object,它允許我將自己的屬性和方法附加到一個元素。 我試圖模擬的行為基本上是這樣的:
// get a button element to wrap
const button = document.querySelector('button');
// some function that wraps new properties/methods around a given element
function wrap(element) {
this.customName = 'John';
this.customAge = 100;
this.printName = function() {
console.log(this.customName);
}
// ...
// ...somehow inherit element fields...
// ...
}
// wrap the button element
const customElement = new wrap(button);
// custom behavior:
console.log(customElement.customAge) // output => 100
customElement.printName() // output => 'John'
// legacy behavior
console.log(customElement.clientHeight) // output => client height
customElement.remove() // => should still call 'remove' on the element
所以,在這里我應該可以添加自己的方法/屬性,但仍然可以正常訪問原始字段。 這可能嗎?
我在這里使用構造函數 function 作為示例只是為了演示預期的行為,但實際上我不知道這是否與解決方案相關。 我是 Javascript 的新手,我對原型和類進行了大量研究,但我仍然對我將在這里采用什么方法感到困惑。
編輯:正如 Brad 在評論中指出的那樣,我還嘗試使用類實現此實現:
class MyButton extends HTMLButtonElement {
constructor() {
super();
this.customName = 'John';
this.customAge = 100;
}
printName() {
console.log(this.customName);
}
}
const myBtn = new MyButton();
但這導致了錯誤: Uncaught TypeError: Illegal constructor
我沒有測試過這個,但也許是這樣的:
// get a button element to wrap const button = document.querySelector('button'); // some function that wraps new properties/methods around a given element function wrap(element) { Object.defineProperties(element, { customName: {value:"John"}, customAge: {value:100}, printName:{value: () => console.log(element.customName)} }) return element } // wrap the button element const customElement = wrap(button); // custom behavior: console.log(customElement.customAge) // output => 100 customElement.printName() // output => 'John' // legacy behavior console.log(customElement.clientHeight) // output => client height customElement.remove() // => should still call 'remove' on the element
<button>Hello world!</button>
可以使用的另一種方法是將元素包裝到proxy()
這將允許在屬性不存在時返回自定義數據,並在屬性更改時發送通知:
const customElement = function (element, properties = {}) { this.element = element; this.customName = 'John'; this.customAge = 100; this.printName = function() { console.log(this.customName); } //override default properties for(let i in properties) { if (i in element) element[i] = properties[i]; else this[i] = properties[i]; } return new Proxy(this, { get(target, prop) { if (prop in target.element) //is property exists in element? { if (target.element[prop] instanceof Function) return target.element[prop].bind(target.element); return target.element[prop]; } else if (prop in target) //is property exists in our object? return target[prop]; else return "unknown property"; //unknown property }, set(target, prop, value, thisProxy) { const oldValue = thisProxy[prop]; if (prop in target.element) target.element[prop] = value; else target[prop] = value; // send notification target.element.dispatchEvent(new CustomEvent("propertyChanged", { detail: { prop, oldValue, value } })); } }); } const button = new customElement(document.createElement("button"), {customName: "Not John"}); button.addEventListener("propertyChanged", e => { console.log("property changed", e.detail); }); button.printName(); console.log("age:", button.customAge); console.log("height:", button.clientHeight); console.log("blah:", button.blah); button.blah = "ok"; console.log("blah:", button.blah);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.