我正在学习Web组件,并正在建立动态列表来掌握它们。开始工作后,我读到最好使用connectedCallback
方法附加阴影根。但是,尝试执行此操作后,出现了很多无法修复的错误。
另外,我为标签设置简单属性的方法似乎有点麻烦:是否有一种更简单的方法来选择属性并将其显示为标签?
这是我的工作示例:
const template = document.createElement('template');
template.innerHTML = `
<style>
:host {
display: block;
font-family: sans-serif;
text-align: center;
}
button {
border: none;
cursor: pointer;
}
ul {
list-style: none;
padding: 0;
}
</style>
<h1>To dos</h1>
<lable id="lable1"></lable>
<select></select>
`;
class TodoApp extends HTMLElement {
constructor() {
super();
this._shadowRoot = this.attachShadow({ 'mode': 'open' });
this._shadowRoot.appendChild(template.content.cloneNode(true));
this.$todoList = this._shadowRoot.querySelector('select');
this.label1 = this._shadowRoot.getElementById('lable1')
}
static get observedAttributes() {
return ['att1'];
}
attributeChangedCallback(name, oldValue, newValue) {
this.label1.innerText = this.getAttribute('att1');
}
renderTodoList() {
this.$todoList.innerHTML = '';
this.todosArray.forEach((todoP) => {
let $todoItem = document.createElement('option');
$todoItem.text = todoP.text;
$todoItem.value = todoP.id;
this.$todoList.appendChild($todoItem);
});
}
set todos(value) {
this.todosArray = value;
this.renderTodoList();
}
}
window.customElements.define('to-do-app', TodoApp);
当我添加一个connectedCallback()
方法并在那里创建影子dom时,我会遇到很多错误。
我的标记是:
<to-do-app att1="value 1 attribute"></to-do-app>
我尝试过:
class TodoApp extends HTMLElement {
constructor() {
super();
this.label1 = '';
}
connectedCallback() {
this._shadowRoot = this.attachShadow({ 'mode': 'open' });
this._shadowRoot.appendChild(template.content.cloneNode(true));
this.$todoList = this._shadowRoot.querySelector('select');
this.label1 = this._shadowRoot.getElementById('lable1')
}
static get observedAttributes() {
return ['att1'];
}
attributeChangedCallback(name, oldValue, newValue) {
this.label1.innerText = this.getAttribute('att1');
}
但是得到错误:
TypeError:无法分配“”上的属性“ innerText”:不是对象
答案 0 :(得分:2)
我是not sure at all it's best to define the Shadow DOM in connectedCallback()
(除非您想使用Shadow DOM polyfill。您在哪里读到的?
无论如何,如果您的示例带有connectedCallback()
,则该错误是由于在attributeChangedCallback()
之前调用了connectedCallback()
。
这就是为什么在调用this.label1
时尚未设置属性attributeChangeCallback()
的原因。
相反,测试属性是否存在:
attributeChangedCallback(name, oldValue, newValue) {
if ( this.label1 )
this.label1.innerText = this.getAttribute('att1');
}
然后,在渲染组件时,测试属性是否存在:
connectedCallback() {
//...
this.label1 = this._shadowRoot.getElementById('lable1')
if ( this.getAttribute( 'att1' ) )
this.label1.innerText = this.getAttribute( 'att1' )
}
更新
读取属性的最佳方法取决于您何时需要它。在您的用例中,由于在connectedCallback()
中需要时它已经存在于标记中,因此只需使用this.getAttribute()
就可以得到它。
Tu分配了它的值,也许您应该使用带有变量的template literal而不是<template>
元素。
let label = this.getAttribute( 'att1' )
this.shadowRoot.innerHTML = `<label>${label}</label>`