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
相关产品推荐
相关产品推荐

