Моя цель - создать класс ObservableElement
, расширяющий HTMLElement
, чтобы его можно было использовать для определения пользовательских элементов, например:
customElements.define('an-observable-elem', class extends ObservableElement {
construct() {
super()
...
}
...
})
Особенность любого элемента, основанного на ObservableElement
, заключается в том, что он должен иметь определенные особенности поведения по отношению к свойствам.
Во-первых, 'whatever' in myElem
должно всегда быть верным. Другими словами, для экземпляра has
я бы хотел ловушку для прокси, которая всегда всегда возвращает true.
Во-вторых, установка и получение любого реквизита должны работать. Но всякий раз, когда устанавливается опора, которая явно не определена в элементе или в цепочке прототипов, я хочу создать пользовательское событие с именем set${propname}
и detail: theValue
.
Кажется, должен быть способ использования es6-прокси. Наивно я впервые попробовал:
class ObservableElement extends HTMLElement {
constructor () {
super()
const vals = {}
return Proxy(this, {
has: _ => true,
get: name => {
if (name in this) return this[name]
if (name in vals) return vals[name]
return null
},
set: (name, value) => {
if (name in this) {
this[name] = value
return
}
if (vals[name] === value) return
vals[name] = value
this.dispatchEvent(new CustomEvent(`set${name}`, {detail: value}))
}
})
}
}
Но, конечно, это не сработало. Возвращение прокси из конструктора не изменило значение this
в конструкторах расширенных классов. Я возился со всевозможными комбинациями проксирования construct
в классе, Object.setPrototypeOf(...)
и т. Д. Безрезультатно.
Я был бы очень признателен, если бы любой, кто понимает, как эти вещи могут сочетаться друг с другом для достижения того, чего я хочу, объяснил бы мне это. Спасибо!