簡體   English   中英

我如何在 Javascript 中創建元素包裝器?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM