Можно ли определить обратные вызовы жизненного цикла в пользовательском элементе HTML5 после регистрации?

В последнее время я работаю с пользовательскими элементами HTML5 и наткнулся на неприятную проблему. Учитывая следующее тело HTML во всех примерах:

<body>
    <h2>Foo elements.</h2>
    <foo-element>One!</foo-element>
    <foo-element>Two!</foo-element>
</body>

И вот этот скрипт, прикрепленный к шапке страницы для регистрации пользовательского элемента:

var HTMLFooElement = document.registerElement('foo-element', {
  prototype: Object.create(HTMLDivElement.prototype, {
    createdCallback: { value: function() {
      console.log('[CALLBACK] created: ', this);
    }},
    attachedCallback: { value: function() {
      console.log('[CALLBACK] attached: ', this);
    }}
  })
});

Приложение будет работать, как и ожидалось, на Chromium версии 41.0.2272.76: объявленные пользовательские элементы будут вызывать оба обратных вызова, выводя в консоль 4 строки.

[CALLBACK] created: <foo-element>One!</foo-element> [CALLBACK] attached: <foo-element>One!</foo-element> [CALLBACK] created: <foo-element>Two!</foo-element> [CALLBACK] attached: <foo-element>Two!</foo-element>

Но теперь у меня был такой вариант использования, когда я должен отложить определение attachedCallback на будущее:

var HTMLFooElement = document.registerElement('foo-element', {
  prototype: Object.create(HTMLDivElement.prototype, {
    createdCallback: { value: function() {
      console.log('[CALLBACK] created: ', this);
    }},
  })
});
HTMLFooElement.prototype.attachedCallback = function() {
  console.log('[CALLBACK] attached: ', this);
};

Оказывается, эта версия не будет запускать attachedCallback, и "прикрепленные" строки журнала не будут напечатаны (jsfiddle) . На данный момент функция, безусловно, будет во всех моих пользовательских элементах в качестве члена, поскольку весь код был выполнен до того, как была обработана body часть DOM. И независимо от этого результат один и тот же при создании и добавлении новых элементов в JavaScript после загрузки документа.

Меня сбивает с толку то, что поздние определения обратного вызова жизненного цикла после регистрации пользовательского тега не применяются. Что я должен сделать, чтобы определить обратный вызов жизненного цикла после вызова registerElement и действительно сделать его эффективным?


person E_net4 the curator    schedule 24.03.2015    source источник
comment
Кажется, это указывает на необходимость перерегистрации вашего элемента (я не уверен, что это вообще возможно), поскольку он не будет обновляться автоматически. Это может быть совершенно неправильно, но соответствует симптомам.   -  person adamdc78    schedule 24.03.2015
comment
Насколько я понимаю, вам нужно привязать пользовательский API перед вызовом registerElement()   -  person wahwahwah    schedule 24.03.2015


Ответы (1)


Процедура регистрации элемента, по-видимому, копирует каждый обратный вызов жизненного цикла внутри, а это означает, что изменение исходного прототипа не оказывает никакого влияния. Мне удалось избежать переопределения в моем проекте, но для тех, кто сталкивается с той же проблемой, введение прокси-сервера — это один из способов ее решения, который не требует перерегистрации элемента.

var protoProxy = {
    createdCallback: function(e) {
        console.log('[CALLBACK] created: ', e);
    },
    attachedCallback: function(e) {
      console.log('[CALLBACK] placeholding ...');
    }
};
var HTMLFooProto = Object.create(HTMLDivElement.prototype, {
  createdCallback: { value: function() {
      protoProxy.createdCallback(this);
  }},
  attachedCallback: { value: function() {
      protoProxy.attachedCallback(this);
    }}
});

var HTMLFooElement = document.registerElement('foo-element', {
  prototype: HTMLFooProto
});

protoProxy.attachedCallback = function(e) {
  console.log('[CALLBACK] attached: ', e);
};

jsFiddle

person E_net4 the curator    schedule 30.03.2015
comment
Ты прав. Спецификация значительно изменилась по сравнению с v0 (не более document.registerElement). В текущей спецификации указано, что обратные вызовы жизненного цикла копируются только тогда, когда элемент определен: w3.org/TR/custom-elements/#element-definition - person Noah Freitas; 22.10.2016