В соответствии с рекомендациями мы обрабатываем атрибут и свойство изменения в атрибуте attributeChangedCallback HTMLElements.Атрибуты различения устанавливаются через HTML, например, <my-element size=3>
;тогда как свойства задаются в js, например, myElement.size = 3
.
Идея состоит в том, что наши подклассы HTMLElement будут иметь установщик размера, который установит атрибут, и позволят нам обрабатывать оба случая в attributeChangedCallback
, например
class MyElement extends HTMLElement {
...
get size() {
return this.getAttribute('size');
}
set size(value) {
this.setAttribute('size', value);
}
attributeChangedCallback(name, oldValue, newValue) {
if (name === 'size') {
// handle size update here
}
}
}
Это кажется хорошей идеей, поскольку позволяет одному месту обрабатывать оба возможных метода обновления размера.На самом деле, это поощряется Руководством по передовым методам Google HTMLElement
При этом это проблематично, учитывая, что атрибуты HTML могут обрабатывать только строки.Итак, у нас есть 2 альтернативы:
1) Не обращайте внимания на рекомендации по передовым методам, которые не являются абсолютно необоснованными, поскольку HTMLE-элементы все еще являются новой вещью, и передовые практики не обязательно основаны на многолетнем опыте работы с ними,Возможно, мы делаем прямо противоположное, делегируя изменения атрибутов изменениям свойств, так как это все равно позволит достичь цели, предложенной Google: «избежать [повторных] проблем с повторным входом» и иметь один обработчик.
class MyElement extends HTMLElement {
...
get size() {
this.size_;
}
set size(value) {
this.size_ = value;
// handle size update here
}
attributeChangedCallback(name, oldValue, newValue) {
this[name] = newValue;
}
}
или 2) Положитесь на сеттеры для свойств, которые можно установить для объектов JS, и attributeChangedCallback для свойств, которые могут быть представлены в виде строк.
class MyElement extends HTMLElement {
...
get size() {
return this.getAttribute('size');
}
set size(value) {
this.setAttribute('size', value);
}
get myObj() {
return this.myObj_;
}
set myObj(value) {
this.myObj_ = value;
// handle myObj update here
}
attributeChangedCallback(name, oldValue, newValue) {
if (name === 'size') {
// handle size update here
}
}
}