You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

StencilJS:在JSX/TSX中渲染原生节点遇undefined问题求助

问题分析与解决方案

核心错误点

  1. 事件绑定拼写错误:原生slotchange事件在Stencil JSX中需用驼峰式onSlotChange(大写C),你写的onSlotchange无法触发事件处理函数,导致rows始终为空。
  2. 重复渲染冲突:同时保留<slot>标签和手动渲染rows,会让浏览器默认渲染插槽内容,同时你手动渲染DOM元素实例,引发逻辑冲突。
  3. 数组更新逻辑错误:每次slotchange都追加元素到rows,会导致多次触发时数组重复添加相同元素。

修正后的代码

import { Component, Element, State, Host } from '@stencil/core';

@Component({
  tag: 'custom-table-body',
  shadow: true
})
export class CustomTableBody {
  @Element() host: HTMLElement;
  @State() private rows: Element[] = [];

  private onSlotChange(event: Event) {
    const slot = event.target as HTMLSlotElement;
    // 获取所有分配到插槽的元素,flatten: true可展开嵌套元素(按需使用)
    const assignedElements = slot.assignedElements({ flatten: true });
    // 过滤仅保留custom-table-row元素(可选,确保行类型正确)
    this.rows = assignedElements.filter(el => el.tagName.toLowerCase() === 'custom-table-row');
  }

  render() {
    return (
      <Host role="rowgroup">
        {/* 隐藏原始插槽,仅用于捕获内容变化 */}
        <slot onSlotChange={(e) => this.onSlotChange(e)} style={{ display: 'none' }} />
        {/* 手动渲染行元素,添加唯一key确保正确重渲染 */}
        {this.rows.map((row, index) => (
          <span key={index}>{row}</span>
          {/* 若无需包裹元素,可改用Fragment:<>{row}</> */}
        ))}
      </Host>
    );
  }
}

关键说明

  • 隐藏原始插槽:避免浏览器默认渲染插槽内容,仅用它监听内容变化。
  • 正确获取插槽元素:assignedElements({ flatten: true })确保拿到所有分配的元素,包括嵌套在其他容器中的行(如果有)。
  • 唯一Key:给每个渲染的行元素添加唯一key,保证组件重渲染时的性能和正确性,优先使用行元素的唯一标识(如id),临时场景可用索引替代。

内容的提问来源于stack exchange,提问作者Marco

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 09:20:37