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

StencilJS嵌套子组件展开与复选框更新异常问题

树形组件嵌套渲染问题及需求

**更新:**已通过拆分渲染函数并传入MenuItem解决渲染问题:

renderItem(item: TreeMenuItem) {
  console.log('render item:', item.label);
  return (
    <div>
      <li>
        {item.children ? <button onClick={this.toggleDisplayChildren}>{this.displayChildren ? 'v' : '>'}</button> : ''}
        {this.showCheckbox ? <input type="checkbox" checked={item.selected} onClick={() => this.selectItem(item)} /> : ''}
        {item.label}
      </li>
      {this.renderChildren(item)}
    </div>
  );
}

renderChildren(item: TreeMenuItem) {
  return item.children && this.displayChildren
    ? item.children.map(child => {
        child.parent = item;
        return this.renderItem(child);
      })
    : '';
}

render() {
  return <Host>{this.renderItem(this.item)}</Host>;
}

核心问题

问题1:递归展开所有层级子组件

已实现嵌套子对象的正确渲染,但选中父组件时仅能展开直接子组件,期望自动递归展开所有层级子组件(含孙组件等)。要求不通过在对象中添加displayChild属性,使用以下代码实现:

@Prop({ mutable: true }) displayChildren = false;
toggleDisplayChildren = () => {
  this.displayChildren = !this.displayChildren;
};

但使用forEach循环时,this始终指向调用子组件的父组件,而非子组件本身。核心需求:父组件displayChildren = true时,其所有含子组件的子元素也需设displayChildren = true。

问题2:复选框状态无法自动更新

复选框状态无法随item.selected变更自动更新,仅当displayChildren变更时才更新。相关代码如下:

selectItem() {
  this.item.selected = !this.item.selected;
  this.isParent() ? this.selectParent() : this.selectChild();
  this.item = { ...this.item };
}

private selectParent() {
  if (!this.isParent()) return;
  if (this.item.indeterminate) this.item.indeterminate = false;
  if (!this.displayChildren) this.displayChildren = true;
  console.log('Selecting parent.');
  if (this.item.children.length === 1) {
    this.item.children[0].selected = this.item.selected;
    console.log('Only one child, so setting same as parent.');
  } else {
    this.item.children.map(child => {
      child.selected = true;
      console.log(`${child.label} selected: ${child.selected}`);
      if (child.children) {
        console.log(`${child.label} has children, so do them too.`);
      }
    });
  }
}

数据源及原渲染代码

数据源

items: TreeMenuItem[] = [
  {
    label: 'Plants',
    value: 'plants',
    children: [
      {
        label: 'Mono-Cotyledons',
        value: 'monocotyledons',
        children: [
          {
            label: 'Coconut',
            value: 'coconut',
            selected: false,
            indeterminate: false,
            disabled: false,
          },
          { label: 'Banana', value: 'banana', selected: false, indeterminate: false, disabled: false },
        ],
        selected: false,
        indeterminate: false,
        disabled: false,
      },
      {
        label: 'Di-Cotyledons',
        value: 'dicotyledons',
        children: [{ label: 'Mango', value: 'mango', selected: false, indeterminate: false, disabled: false }],
        selected: false,
        indeterminate: false,
        disabled: false,
      },
    ],
    selected: false,
    indeterminate: false,
    disabled: false,
  },
];

原渲染代码

render() {
  return (
    <div>
      <li>
        {this.item.children ? <button onClick={this.toggleDisplayChildren}>{this.displayChildren ? 'v' : '>'}</button> : ''}
        {this.showCheckbox ? <input type="checkbox" checked={this.item.selected} onClick={() => this.selectItem()} style={{ color: 'red' }} /> : ''}
        {this.item.label}
      </li>
      {this.item.children && this.displayChildren
        ? this.item.children.map(child => {
            child.parent = this.item;
            return <menu-item item={child} class="child-item"></menu-item>;
          })
        : ''}
    </div>
  );
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 21:01:22