问题描述
我想为每个孩子创建 <slot>
,例如这里我有一个菜单,我希望每个孩子都被放置在一个 <div>
和 item
类中。
我创建了一个小实用函数来映射孩子:
export function ChildrenMap(el: LitElement,map: (el: HTMLElement,index: number) => TemplateResult): TemplateResult[] {
console.log(el.children.length) // Returns 0 in Google Chrome and I guess Edge too.
return (Array.prototype.slice.call(el.children) as HTMLElement[])
.map(map);
}
然后我在渲染函数中使用它:
render() {
return html`
<nav>
${ChildrenMap(this,(ele,index) => {
let id = ele.id ? ele.id : `item-${index}`;
ele.setAttribute('slot',id);
let klass = 'item';
if(this.selected && this.selected == index) {
klass += " selected";
}
return html`
<div class="${klass}" data-index="${index}">
<slot name="${id}"></slot>
</div>`;
})}
</nav>
`;
}
这在 FireFox 中运行良好,但正如我上面的评论所说,在 Google Chrome 中,元素在渲染点有 0 个子元素,因此 <nav>
为空。
谁能解释为什么元素在渲染时有 0 个子元素?
也许我以错误的方式解决这个问题,有人有其他选择吗?
非常感谢
解决方法
更新:Mozilla/FireFox 于 2021 年初修复了此错误
实际上 FireFox 在这一点上是错误的,它调用了 connectedCallback
为时已晚
Mozilla 工程师 Anne van Kesteren 确认的错误:
有关详细信息,请参阅 StackOverflow 线程:
在 connectedCallback
中还没有 要读取的 DOM 子项,因为所有 DOM 子项仍在解析中。 (它可能是一个非常大的 DOM 结构)
解决方法(如您所见)是等待:
connectedCallback(){
setTimeout(()=>{
// now you can access this. DOM children
},0);
}
所有带有 Promises 等的建议都有效地执行相同的操作:等待事件循环为空
- 事件循环到底是什么? - 菲利普·罗伯茨
https://www.youtube.com/watch?v=8aGhZQkoFbQ