具有代理的自定义元素具有、获取和设置
Custom elements with proxied has, get & set
我的目标是创建一个 class ObservableElement
扩展 HTMLElement
以便它可以用来定义自定义元素,例如:
customElements.define('an-observable-elem', class extends ObservableElement {
construct() {
super()
...
}
...
})
关于任何基于 ObservableElement
的元素的事情是它应该有一些特定的行为 wrt 属性。
首先,'whatever' in myElem
应该总是 为真。换句话说,我想要实例上 has
的代理陷阱,它总是 returns true.
其次,设置和获取任何道具都应该有效。但是每当设置了未在元素或原型链中明确定义的道具时,我想发出一个名为 set${propname}
和 detail: theValue
.
的自定义事件
看来一定有办法使用es6-proxies。天真地,我第一次尝试:
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}))
}
})
}
}
但这当然行不通。从构造函数返回代理并没有改变扩展 classes 的构造函数中的 this
值。我在 class、Object.setPrototypeOf(...)
等上尝试了各种代理 construct
的组合,但都无济于事。
如果有人了解这些东西如何组合在一起以实现我想要的东西,请向我解释一下,我将不胜感激。谢谢!
W3C Web 组件规范不支持您尝试执行的操作。
According to §2.4 of the W3C Web Components specification, step 10.6.2:
If observedAttributesIterable
is not undefined
, then set observedAttributes
to the result of converting observedAttributesIterable
to a sequence<DOMString>
. Rethrow any exceptions from the conversion.
这发生在 customElements.define()
执行期间,这意味着您必须在定义 class 时为每个可能的字符串定义一个可迭代对象,以便拦截所有属性更改。
如果组件在该序列中找不到更改的 属性,它不会调用 attributeChangedCallback()
。
同样不可能 return 来自 constructor
的代理,因为 the restriction in §2.2:
A return
statement must not appear anywhere inside the constructor body, unless it is a simple early-return (return
or return this
).
我的目标是创建一个 class ObservableElement
扩展 HTMLElement
以便它可以用来定义自定义元素,例如:
customElements.define('an-observable-elem', class extends ObservableElement {
construct() {
super()
...
}
...
})
关于任何基于 ObservableElement
的元素的事情是它应该有一些特定的行为 wrt 属性。
首先,'whatever' in myElem
应该总是 为真。换句话说,我想要实例上 has
的代理陷阱,它总是 returns true.
其次,设置和获取任何道具都应该有效。但是每当设置了未在元素或原型链中明确定义的道具时,我想发出一个名为 set${propname}
和 detail: theValue
.
看来一定有办法使用es6-proxies。天真地,我第一次尝试:
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}))
}
})
}
}
但这当然行不通。从构造函数返回代理并没有改变扩展 classes 的构造函数中的 this
值。我在 class、Object.setPrototypeOf(...)
等上尝试了各种代理 construct
的组合,但都无济于事。
如果有人了解这些东西如何组合在一起以实现我想要的东西,请向我解释一下,我将不胜感激。谢谢!
W3C Web 组件规范不支持您尝试执行的操作。
According to §2.4 of the W3C Web Components specification, step 10.6.2:
If
observedAttributesIterable
is notundefined
, then setobservedAttributes
to the result of convertingobservedAttributesIterable
to asequence<DOMString>
. Rethrow any exceptions from the conversion.
这发生在 customElements.define()
执行期间,这意味着您必须在定义 class 时为每个可能的字符串定义一个可迭代对象,以便拦截所有属性更改。
如果组件在该序列中找不到更改的 属性,它不会调用 attributeChangedCallback()
。
同样不可能 return 来自 constructor
的代理,因为 the restriction in §2.2:
A
return
statement must not appear anywhere inside the constructor body, unless it is a simple early-return (return
orreturn this
).