Angular6中ViewChildren绑定数据更新后宿主未变化的问题求助
嗨,这个问题我之前也碰到过,咱们一步步来解决~
首先得纠正一个小错误:你把@ViewChildren的类型声明成了DemoDirective[],但实际上ViewChildren返回的是**QueryList<DemoDirective>**,这是Angular专门用来管理视图查询结果的可观察集合。如果直接用数组类型,Angular只会在初始化时把QueryList转成数组赋值给你,后续视图更新时,这个数组不会自动同步,这就是你看到数量不变的核心原因!
接下来给你具体的解决步骤:
1. 修正类型声明
把组件里的compHosts改成QueryList类型:
import { ViewChildren, QueryList, AfterViewInit } from '@angular/core'; // 导入你的DemoDirective export class YourParentComponent implements AfterViewInit { componentNames = ['comp1', 'comp2']; // 用QueryList类型声明 @ViewChildren(DemoDirective) compHosts!: QueryList<DemoDirective>; // ...其他代码 }
2. 监听查询结果的变化
QueryList自带一个changes可观察对象,你可以在ngAfterViewInit生命周期钩子中订阅它,这样每次视图更新导致指令实例变化时,你都能拿到最新的集合:
ngAfterViewInit() { // 订阅变化事件 this.compHosts.changes.subscribe(() => { const currentDirectives = this.compHosts.toArray(); console.log('最新的指令数量:', currentDirectives.length); // 这里可以处理更新后的逻辑 }); // 初始化时也能获取一次结果 const initialDirectives = this.compHosts.toArray(); console.log('初始指令数量:', initialDirectives.length); }
3. 确保componentNames的更新能触发变更检测
另外要注意,更新componentNames时要用不可变的方式,比如不要用push/splice修改原数组,而是创建新数组:
// 正确的更新方式 updateComponentNames() { // 用扩展运算符生成新数组,Angular能检测到变化 this.componentNames = [...this.componentNames, 'newComp']; }
如果用this.componentNames.push('newComp'),Angular的变更检测可能无法感知到数组内容的变化,导致*ngFor不更新视图,自然compHosts也不会变。
额外说明:关于ng-template的小提醒
你模板里用了<ng-template demo-directive>,要确认DemoDirective是属性型指令(不是结构型指令)。如果是结构型指令(带*语法的那种),ng-template会被指令处理成实际的DOM节点,这时候查询逻辑可能需要调整,但从你的代码看应该是普通属性指令,没问题~
这样调整后,当你更新componentNames时,*ngFor会新增/删除对应的div和里面的ng-template,compHosts的QueryList就会自动更新,你通过changes订阅或者直接调用toArray()就能拿到最新的指令实例啦!
内容的提问来源于stack exchange,提问作者user3006967

