Хорошо. Отложив на минутку, что я думаю, что это плохая сомнительная идея, вот код, который должен делать то, что вы хотите (я не запускал его, но он должен работать):
class FooElement extends HTMLElement {
constructor () {
super();
this.attachShadow({ mode: 'open' });
this.shadowRoot.appendChild(document.importNode(template.content, true));
}
_xformObject (object) {
// turn the obj into DOM nodes
}
renderFromObject (object) {
// you may need to do something fancier than appendChild,
// you can always query the shadowRoot and insert it at
// a specific point in shadow DOM
this.shadowRoot.appendChild(this._xformObject(object));
}
}
Вы, конечно, должны будете зарегистрировать пользовательский элемент.
Теперь иногда вы действительно не можете уйти от подобных действий. Но это должно быть абсолютное последнее средство . Смотрите ниже:
Почему я думаю, что это плохая сомнительная идея и как ее улучшить:
Одним из основных преимуществ веб-компонентов является то, что они допускают декларативную разметку HTML, а не процедурные манипуляции с JS DOM. Хотя предоставление API, о котором вы говорите, безусловно, является большим шагом вперед, например. создание таблицы путем создания узла таблицы, создания узла строки, создания некоторых тд, добавления их к строке, а затем добавления этого к таблице, я (и я думаю, что большинство) разработчиков считают, что если ваш пользовательский элемент требует непосредственного манипулирования JavaScript пользователем, тогда это на самом деле не элемент HTML: это интерфейс JavaScript.
Позвольте мне немного уточнить это. Когда я говорю «требует» JavaScript, я имею в виду, что нет способа поместить его на страницу с некоторыми соответствующими атрибутами и получить нужную вещь. Когда я говорю «прямой», я имею в виду непосредственный вызов методов представления объекта элемента, а не переключение атрибута элемента. Чтобы поставить мою точку в коде:
// good
myCustomElement.setAttribute("toggled-on", true);
// this isn't *bad*, but don't *force* people to do this
myCustomElement.toggleState();
Возможно, вы по-прежнему захотите предоставить второй как часть вашего общедоступного API для удобства пользователей, но , требующий , кажется за гранью. Теперь одна проблема заключается в том, что вы, очевидно, не можете легко передать сложные структуры данных в атрибут HTML (у Polymer есть помощники для этого, если вы используете Polymer).
Но если это так, то вместо того, чтобы быть частью API элемента, я бы предоставил отдельную функцию, которая возвращает соответствующую структуру DOM, а не заполняет ее элементом. Вы даже можете сделать это методом класса вашего класса пользовательских элементов, если вы так катитесь.
Рассмотрим случай, когда у вас есть элемент List, который отображает произвольное количество элементов Item. Я думаю, что это здорово, предоставить удобный метод, который принимает массив и обновляет (легкий) DOM. Но пользователи должны иметь возможность добавлять их напрямую.
Ваш вариант использования может потребовать взлома вокруг этой проблемы. Иногда вам действительно нужно использовать антипаттерн. Но подумайте внимательно, так ли это в вашей стихии.