关于单步调试AngularviewQuery的idselector问题
时间:2023-04-03 01:17:11
HTML
问题描述我有这样一个AngularComponent,模板文件如下:@Component({selector:'example-app',template:`1
2 已选择:{{selectedPane}}
`,})在它的Component实现中,我希望在运行时通过@ViewChild获得id为`panel1?`的div元素的实例。exportclassViewChildComp{constructor(publicchangeDetectorRef:ChangeDetectorRef){}@ViewChild("panel1?")setpanethis(v){//setTimeout(()=>this.selectedPane=v.id,0);this.selectedPane=v.id;this.changeDetectorRef.detectChanges();//Promise.resolve().then(()=>this.selectedPane=v.id);}但是运行的时候并没有得到预期的结果,一个报错:>ERRORTypeError:Cannotreadpropertiesofundefined(reading'id')atViewChildComp.set(ng-content.component.ts:57:27)atViewChildComp_Query(template.html:3:5)atexecuteViewQueryFn(core.js:8758:5)在refreshView(core.js:7437:13)在refreshComponent(core.js:8527:13)在refreshChildComponents(core.js:7186:9)在refreshView(core.js:7430:13)atrefreshComponent(core.js:8527:13)atrefreshChildComponents(core.js:7186:9)atrefreshView(core.js:7430:13)#问题分析我们点击上图中高亮的`template.html`调用栈:来到我们自己的Component模板文件,因为这是一个内联到Component中的模板,所以显示为`template.html`:通过单步调试,可以在`refreshView`中,执行`viewquery`的入口逻辑:&&assertDefinviewQueryFn,'必须定义要执行的视图查询函数。');setCurrentQueryIndex(0);viewQueryFn(flags,component);}根据关键字`viewquery`查询Angular官网,发现在view查询中使用id选择器的正确语法不是直接查询HTML元素的id属性,而是使用其中的符号HTML元素或`ng-template`#`指定一个id,然后将此id传递给`@ViewChild`:修改后运行效果:#Summary视图查询在父Component需要访问其子Component的场景下特别有用假设有一个alertComponent:@Component({selector:'alert',template:`
{{type}}}
`,})exportclassAlertComponent{@Input()type:string="success";alert(){console.log("alert");}}in我们的parentComponent中,可以定义AlertComponent的多个实例:@Component({selector:'my-app',template:`
`,})exportclassApp{@ViewChildren(AlertComponent)alerts:QueryListngAfterViewInit(){this.alerts.forEach(alertInstance=>console.log(alertInstance));}我们可以使用@ViewChildren装饰器从宿主视图中获取元素。@ViewChildren装饰器支持指令或组件类型作为参数,或模板变量的名称。当参数是组件/指令时,返回值将是组件/指令实例。上例中的console.log语句会打印AlertComponent的实例: