Моя цель — создать класс 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(...)
и т.д. безрезультатно.
Я был бы очень признателен, если бы кто-нибудь, кто понимает, как эти вещи могут сочетаться друг с другом для достижения того, чего я хочу, объяснил бы мне это. Спасибо!
target
, поэтому вы используете неправильные значения. - person Patrick Roberts   schedule 07.06.2019constructor
, вернув объект, отличный отthis
, иначе вы получите ошибкуUncaught DOMException: custom element constructors must call super() first and must not return a different object
, поэтому инкапсуляция экземпляра класса с помощьюProxy
невозможна. - person Patrick Roberts   schedule 07.06.2019construct
. Я просто не могу понять, как собрать части вместе... - person Zach   schedule 10.06.2019HTMLElement
.Proxy
— это экзотический объект, не имеющий встроенногоprototype
(его прототип унаследован от объекта, который он инкапсулирует), поэтому DOM не примет его как экземплярHTMLElement
. - person Patrick Roberts   schedule 10.06.2019