Почему пользовательский элемент не работает должным образом на статической странице?

(первоначально с https://github.com/w3c/webcomponents/issues/392, переехали сюда)

Я работаю над библиотекой (на http://infamous.io, по крайней мере сейчас), в которой я создание набора пользовательских элементов для рендеринга 3D-сцены. Библиотека регистрирует два элемента: [<motor-scene>](https://github.com/infamous/infamous/blob/master/src/motor-html/scene.js) и <motor-node>. . Библиотека зависит от этого document.registerElement полифилла для неподдерживающих браузеров.

У меня есть небольшая проблема. Все работает нормально, когда я использую пользовательские элементы в <body> приложения Meteor, но когда я пытаюсь сделать то же самое со статической HTML-страницей и сценариями, вручную включенными в <head>, это не работает и не работает должным образом. Я не уверен, что я делаю что-то не так и чего-то не знаю о пользовательских элементах, или это проблема с API.

Чтобы увидеть рабочую демонстрацию, просто

git clone [email protected]:trusktr/site.git
cd site
git checkout infamous-motor-html # it's on this branch.
npm install
meteor # meteor is really easy to install, meteor.com
# visit localhost:3000

Результат выглядит так: бирюзовый и розовый элементы расположены в 3D-пространстве, как и ожидалось:

working

Теперь, если вы посмотрите в папку public, вы увидите статическую версию в html-demo.html. Вы можете открыть его прямо в браузере с помощью file:// или посетить localhost:3000/html-demo.html во время работы приложения Meteor. Я перепроверил, и я считаю, что делаю то же самое, что и в версии Meteor, но я просто не могу получить ожидаемый результат, и это выглядит так:

не работает

Я не уверен, в чем проблема и почему это работает в версии Meteor (Meteor 1.3 компилирует код с помощью Babel) и не работает в статической версии (также скомпилированной с Babel через Webpack).

Я добавил console.logs к методам createdCallback, attachedCallback и т. д. в вызовах registerElement (например). Это показывает два разных порядка вывода в консоли.

Вывод для версии Meteor:

выход метеора

Вывод для статической версии:

static-output

Может ли быть проблема с порядком загрузки? Существуют ли какие-либо правила, когда следует вызывать registerElement? Я попытался разместить статические скрипты в конце страницы, что меняет порядок вывода, но все равно отображает то же самое (сломанное, не похоже на версию Meteor).

Любые идеи? Есть ли что-то о пользовательских элементах, чего я не знаю? Почему статический пример не выглядит так же, как пример Meteor?

Примечание. Я получаю такое же непоследовательное поведение между Meteor и static при использовании WebReflection/document-register-element. полифилл, а когда нет.


person trusktr    schedule 22.02.2016    source источник
comment
Пожалуйста, добавьте сюда информацию, которую вы разместили в выпуске GitHub. Они вполне могут удалить этот вопрос, и тогда этот вопрос не будет иметь никакого смысла.   -  person Heretic Monkey    schedule 23.02.2016
comment
@MikeMcCaughan Спасибо. Обновлено.   -  person trusktr    schedule 23.02.2016
comment
Я не понимаю вашего вопроса. Пользовательские элементы работают на статических страницах. В ваших журналах я вижу, что пользовательские элементы зарегистрированы и созданы, поэтому проблема не связана с registerElement. Вы должны попробовать с простым примером.   -  person Supersharp    schedule 23.02.2016
comment
@Supersharp Думаю, да, но что-то другое. В Meteor Blaze компоненты добавляются на страницу позже, динамически. В статической версии компоненты существуют в разметке при извлечении страницы и до анализа разметки HTML. Возможно, что-то происходит асинхронно где-то, против чего я гоняюсь, и я еще не нашел, что это такое.   -  person trusktr    schedule 28.02.2016


Ответы (1)


Если действительно ваша проблема заключается в состоянии гонки между создаваемыми элементами, то ваш элемент может подождать, пока все другие элементы, от которых он зависит, не будут созданы/прикреплены.

Тогда порядок загрузки не будет иметь значения, и вы сможете размещать свои скрипты где угодно.

См. мой ответ здесь: Как для выполнения скрипта при обновлении пользовательского элемента

person MarcG    schedule 06.03.2016
comment
Спасибо @MarcG! В этом ответе, который вы связали, вы используете синтаксис класса ES6 для определения ваших пользовательских элементов. Как это работает? Я думал, что document.registerElement принимает только имя и прототип, а не конструктор класса? - person trusktr; 07.03.2016
comment
Если CustomX ваш класс: document.registerElement("custom-x", CustomX); - person MarcG; 07.03.2016
comment
Интересно, что он работает в Chrome с включенным экспериментальным JavaScript (поэтому не готов к работе, если он также не работает с шаблоном конструктора ES5). Однако класс constructor() {} не увольняется; браузер каким-то образом обходит это. В моем тесте он выстрелил createdCallback без срабатывания constructor. Документация, которую я нашел до сих пор, показывает метод предоставления объекта параметров с prototype, и я также где-то читал, что классы не поддерживаются из-за того, как работает document.registerElement, что, очевидно, больше не соответствует действительности. Где это задокументировано? - person trusktr; 07.03.2016
comment
Также кажется, что document.registerElement возвращает новый конструктор, который нам нужно использовать, если мы хотим создавать новые экземпляры. Я предполагаю, что мы не можем использовать наш исходный конструктор класса? РЕДАКТИРОВАТЬ: интересно, когда я пытаюсь использовать класс напрямую, как в document.body.appendChild(new CustomX()), Chrome выдает Uncaught ReferenceError: this is not defined, и ошибка указывает на строку с определением конструктора. В итоге я использовал этот шаблон: trusktr.io:7777/eqogedadol.js - person trusktr; 07.03.2016
comment
Обновлен фрагмент, мы можем фактически переназначить тот же идентификатор CustomX, так что это похоже на компонент более высокого порядка: trusktr .io:7777/ijirusogud - person trusktr; 07.03.2016
comment
Свеооооооооооооооооооооо. Я только что проверил, он работает и с функциями конструктора ES5, никаких флагов не требуется. Откуда ты узнал об этом? - person trusktr; 07.03.2016
comment
О, дууууу!!! Параметр options должен иметь свойство prototype, поэтому, очевидно, если мы передаем функцию-конструктор через параметр options, то она будет работать, так как функция будет иметь свойство prototype! Дох!!! - person trusktr; 07.03.2016
comment
@trusktr В любом случае, вы решили свою первоначальную проблему? - person MarcG; 08.03.2016
comment
Да, действительно. :] - person trusktr; 17.03.2016