出于純粹的教育和好奇心目的,我正在嘗試創建一個元素包裝器物件,它允許我將自己的屬性和方法附加到元素上。我試圖模擬的行為基本上是這樣的:
// 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
所以,在這里我應該能夠添加我自己的方法/屬性,但仍然可以正常訪問原始欄位。這甚至可能嗎?
我在這里使用建構式作為示例只是為了演示預期的行為,但我實際上并不知道這是否與解決方案相關。我是 Javascript 的新手,我已經對原型和類進行了大量研究,但我仍然對我將在這里采用什么方法感到困惑。
編輯:正如布拉德在評論中指出的那樣,我也使用類嘗試了這個實作:
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
uj5u.com熱心網友回復:
我沒有對此進行測驗,但可能是這樣的:
// 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>
uj5u.com熱心網友回復:
可以使用的另一種方法是將元素包裝到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);
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/453997.html
標籤:javascript 哎呀 遗产 元素 包装
