当前位置: 首页 > Web前端 > HTML5

关于单步调试AngularviewQuery的idselector问题

时间:2023-04-05 20:25:24 HTML5

问题描述我有这样一个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)![](https://img-blog.csdnimg.cn/img_convert/1d29328a6be49ed1e119745caefa63b1.png)#问题分析我们点击上图中高亮的`template.html`调用栈:来到我们自己的Component模板文件,因为这是一个内联到Component中的模板,所以显示为`template.html`:![](https://img-blog.csdnimg.cn/img_convert/2140eff3d8570bd0f22607150cef7b20.png)通过单步调试,可以在`refreshView`中,执行`viewquery`的入口逻辑:&&assertDefinviewQueryFn,'必须定义要执行的视图查询函数。');setCurrentQueryIndex(0);viewQueryFn(flags,component);}![](https://img-blog.csdnimg.cn/img_convert/304d594c84cfd4e2af5c0c95c43270fc.png)根据关键字`viewquery`查询Angular官网,发现在view查询中使用id选择器的正确语法不是直接查询HTML元素的id属性,而是使用其中的符号HTML元素或`ng-template`#`指定一个id,然后将此id传递给`@ViewChild`:![](https://img-blog.csdnimg.cn/img_convert/14ecb16c8af684711c957e70f9680995.png)![](https://img-blog.csdnimg.cn/img_convert/12cf2562baa0833a139a44357be??d480a.png)修改后运行效果:![](https://img-blog.csdnimg.cn/img_convert/f2b7c1b02f4381e00dc5908a9c1effac.png)#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的实例:![](https://img-blog.csdnimg.cn/img_convert/cbc8a51a3073e5da4c11f58b960c6326.png)