Angular8 实战(十六)在模板中引用多个元素

上一章学习了在组件类中通过ViewChild去引用模板中的元素,是通过引用名引用的。但是ViewChild不只可以指定引用名引用,也可以指定组件类型来引用。

@ViewChild

比如引用image-slider组件,那么使用方法如下:

<app-image-slider [sliders]="imageSliders"></app-image-slider>
@ViewChild('ImageSliderComponent', { static: true }) imageSlider: ImageSliderComponent;

所以,如果想引用模板中的Angular组件,@ViewChild中,可以使用引用名,也可以使用组件类型。

@ViewChildren

上面说的是单个模板的引用,如果想引用多个模板元素该如何处理呢?
比如,想选中image-slider中所有的轮播图图片,如果继续使用@ViewChild,那么对于相同命名的,ViewChild只会选中ngFor中的第一个元素,并不会选中整个img元素。这就引出了@ViewChildren可以选中整个img数组。

<img #img *ngFor="let slider of sliders" [src]="slider.imgUrl" [alt]="slider.caption">
@ViewChildren('img') imgs: QueryList<ElementRef>;

所以,可以使用@ViewChildren,在@ViewChildren中可以使用引用名或者使用Angular组件/指令的类型。声明类型为QueryList<?>

打印出imgs看一下效果:


16-1.gif

可以看出这个时候并没有打印出imgs属性,为什么呢?这就用到前面学习的知识了:组件的生命周期。
ngOnInit的时候,视图并没有初始化完成。ngAfterViewInit是视图初始化完成。
再来看一下效果:


16-2.gif

Renderer2

之前讲过,Angular是不推荐直接操作DOM的。那么Angular推荐使用什么呢?
没错,推荐使用Renderer2。
先来看一下用法示例


16-3.gif

那么问题来了,为什么我们要这样用呢?直接写不好吗?
解释一下:如果直接操作DOM,即自己写html节点,可能会造成XSS攻击。比如我们的应用是允许用户自己写一段Html代码传到组件类中,这个时候你不确定用户是否是恶意写入的攻击代码,这其实就属于XSS攻击。
Renderer2是渲染器,默认情况下,Angular会把模板渲染成DOM,同时会检查恶意代码的注入。

总结
@ViewChild用来在类中引用模板中的视图节点,既可以是Angular组件,也可以是HTML元素
在AfterViewInit中可以安全的使用@ViewChild引用的元素
推荐使用Renderer2操作DOM元素

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容