ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
[TOC] >[success] # 在组件类中引用模版(类似vue 的 ref) >[success] ## 获取普通dom 元素 ![](https://img.kancloud.cn/7b/0a/7b0a83c457fa51a828f060ae2fa71516_1012x536.png) 这个好像 **vue2.x** 中的根据 **ref 调用子组件方法** ,我们首先在想要获取dom的标签身上添加 `#名称` ,例子: **html代码** ~~~ <div class="container"> <div class="image-slider" #imageSlider> // 名称 <img *ngFor="let slider of sliders" [src]="slider.imgUrl" [alt]="slider.caption" /> </div> <div class="nav-section"> <span *ngFor="let _ of sliders; let idx = index" class="slide-button" ></span> </div> </div> ~~~ **ts代码** ~~~ import { Component, ElementRef, Input, OnInit, ViewChild } from '@angular/core'; export interface ImageSlider { imgUrl: string; link: string; caption: string; } @Component({ selector: 'app-image-slider', templateUrl: './image-slider.component.html', styleUrls: ['./image-slider.component.css'] }) export class ImageSliderComponent implements OnInit { @Input() sliders: ImageSlider[] = []; // 获取dom元素 @ViewChild('imageSlider', { static: true }) imgSlider!: ElementRef; constructor() {} ngOnInit() { // 对 dom 进行操作 this.imgSlider.nativeElement.innerHTML = `<span>Hello</span>`; } } ~~~ 然后在获取 **dom** 的 **ts** 代码中,像上面这样写,用 **@ViewChild 装饰器选择** 我们定义好的 **#名称** 的标签,这里需要 **注意:如果我们获取的这个 dom 元素在 ng-if 或者 ng-for 包含下,static 就需要设置为 false,如果没有被 ng-if 或者 ng-for 包裹,就设置为 true,默认 false** ,然后起一个变量 **imgSlider** 来储存这个接收 **dom元素** 的 **ref** ,然后 **ElementRef** 是 **dom元素** 的 **类型** 。 >[success] ## 获取angular组件元素 ![](https://img.kancloud.cn/93/63/9363726a35421508fd19991941b8fcbe_1064x508.png) >[success] ### 普通方式获取 代码如下: **html代码** ~~~ <!-- 引入组件 --> <app-scrollable-tab [menus]="topMenus" (tabSelected)="handleTabSeleted($event)" [backgroundColor]="scrollableTabBgColor" titleColor="#fff" titleActiveColor="yellow" indicatorColor="yellow" *ngIf="scrollableTabBgColor === 'red'" > </app-scrollable-tab> <app-image-slider [sliders]="imageSliders" #imageSlider></app-image-slider> ~~~ **ts代码** ~~~ import { AfterViewInit, Component, ViewChild } from '@angular/core'; import { TopMenu, ImageSlider, ImageSliderComponent } from './components'; // 引入子组件中定义得接口 @Component({ selector: 'app-root', // 组件名称 templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) // 以下是类似vue的变量跟方法 export class AppComponent implements AfterViewInit { @ViewChild('imageSlider') imageSlider!: ImageSliderComponent; // selectedIndex = -1; // 高亮选中的颜色下标 topMenus: TopMenu[] = [ // 菜单列表 { title: '热门', link: '' }, { title: '男装', link: '' }, { title: '百货', link: '' }, { title: '运动', link: '' }, { title: '手机', link: '' }, { title: '家纺', link: '' }, { title: '食品', link: '' }, { title: '电器', link: '' }, { title: '鞋包', link: '' }, { title: '汽车', link: '' }, { title: '水果', link: '' }, { title: '电脑', link: '' }, { title: '内衣', link: '' }, { title: '家装', link: '' }, { title: '母婴', link: '' }, { title: '美妆', link: '' }, { title: '家具', link: '' } ]; scrollableTabBgColor = 'red'; imageSliders: ImageSlider[] = [ { imgUrl: 'https://s.cn.bing.net/th?id=OIP-C.kB-Ovasi0GW67-rmwnAcwAHaEo&w=316&h=197&c=8&rs=1&qlt=90&o=6&pid=3.1&rm=2', link: '', caption: '' }, { imgUrl: 'https://s.cn.bing.net/th?id=OIP-C.nfC2tVNM9TgwQ5QuqECd6wHaFj&w=288&h=216&c=8&rs=1&qlt=90&o=6&pid=3.1&rm=2', link: '', caption: '' }, { imgUrl: 'https://s.cn.bing.net/th?id=OIP-C.rHuc8SKa0wLVwCqqA27uIwHaEt&w=313&h=199&c=8&rs=1&qlt=90&o=6&pid=3.1&rm=2', link: '', caption: '' }, { imgUrl: 'https://s.cn.bing.net/th?id=OIP-C.i0-ND27ia6sO-nZuY9f7qAHaEK&w=333&h=187&c=8&rs=1&qlt=90&o=6&pid=3.1&rm=2', link: '', caption: '' } ]; handleTabSeleted(tabMenu: TopMenu) { const colors = ['red', 'blue', 'black']; const idx = Math.floor(Math.random() * 3); this.scrollableTabBgColor = colors[idx]; } ngAfterViewInit(): void { console.log(this.imageSlider, '获取angular的组件'); } } ~~~ >[success] ### 快速方式获取 区别: 1. **html 代码** 中的 **组件标签上** 不用声明 **#名称** 2. **ts 代码中** 的 **@ViewChild** 装饰器不用传入 **#名称** ,**直接传入组件** ,如下图: ![](https://img.kancloud.cn/7b/6d/7b6da6a7a30f85e48f0147f4000af8ea_1047x670.png) 具体代码如下: **html代码** ~~~ <!-- 引入组件 --> <app-scrollable-tab [menus]="topMenus" (tabSelected)="handleTabSeleted($event)" [backgroundColor]="scrollableTabBgColor" titleColor="#fff" titleActiveColor="yellow" indicatorColor="yellow" *ngIf="scrollableTabBgColor === 'red'" > </app-scrollable-tab> <app-image-slider [sliders]="imageSliders"></app-image-slider> ~~~ **ts代码** ~~~ import { AfterViewInit, Component, ViewChild } from '@angular/core'; import { TopMenu, ImageSlider, ImageSliderComponent } from './components'; // 引入子组件中定义得接口 @Component({ selector: 'app-root', // 组件名称 templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) // 以下是类似vue的变量跟方法 export class AppComponent implements AfterViewInit { @ViewChild(ImageSliderComponent) imageSlider!: ImageSliderComponent; // selectedIndex = -1; // 高亮选中的颜色下标 topMenus: TopMenu[] = [ // 菜单列表 { title: '热门', link: '' }, { title: '男装', link: '' }, { title: '百货', link: '' }, { title: '运动', link: '' }, { title: '手机', link: '' }, { title: '家纺', link: '' }, { title: '食品', link: '' }, { title: '电器', link: '' }, { title: '鞋包', link: '' }, { title: '汽车', link: '' }, { title: '水果', link: '' }, { title: '电脑', link: '' }, { title: '内衣', link: '' }, { title: '家装', link: '' }, { title: '母婴', link: '' }, { title: '美妆', link: '' }, { title: '家具', link: '' } ]; scrollableTabBgColor = 'red'; imageSliders: ImageSlider[] = [ { imgUrl: 'https://s.cn.bing.net/th?id=OIP-C.kB-Ovasi0GW67-rmwnAcwAHaEo&w=316&h=197&c=8&rs=1&qlt=90&o=6&pid=3.1&rm=2', link: '', caption: '' }, { imgUrl: 'https://s.cn.bing.net/th?id=OIP-C.nfC2tVNM9TgwQ5QuqECd6wHaFj&w=288&h=216&c=8&rs=1&qlt=90&o=6&pid=3.1&rm=2', link: '', caption: '' }, { imgUrl: 'https://s.cn.bing.net/th?id=OIP-C.rHuc8SKa0wLVwCqqA27uIwHaEt&w=313&h=199&c=8&rs=1&qlt=90&o=6&pid=3.1&rm=2', link: '', caption: '' }, { imgUrl: 'https://s.cn.bing.net/th?id=OIP-C.i0-ND27ia6sO-nZuY9f7qAHaEK&w=333&h=187&c=8&rs=1&qlt=90&o=6&pid=3.1&rm=2', link: '', caption: '' } ]; handleTabSeleted(tabMenu: TopMenu) { const colors = ['red', 'blue', 'black']; const idx = Math.floor(Math.random() * 3); this.scrollableTabBgColor = colors[idx]; } ngAfterViewInit(): void { console.log(this.imageSlider, '获取angular的组件'); } } ~~~ >[success] ## 获取 ng-for 循环添加的 ref 元素 ![](https://img.kancloud.cn/5d/43/5d43618c8c193099dc6cd96a0648026a_958x544.png) 获取 **ng-for 循环** 出来的 **dom 元素** ,需要使用 **@ViewChildren 装饰器** ,定义类型时使用 **QueryList<ElementRef\>** 才可以,然后下面还使用了 **angular** 提供的注入中的 **Renderer2** 方法,来 **修改dom 元素样式** 具体写法如下: **html代码** ~~~ <div class="container"> <div class="image-slider" #imageSlider> <img #img // 定义dom选择的名称 *ngFor="let slider of sliders" [src]="slider.imgUrl" [alt]="slider.caption" /> </div> <div class="nav-section"> <span *ngFor="let _ of sliders; let idx = index" class="slide-button" ></span> </div> </div> ~~~ **ts代码** ~~~ import { Component, ElementRef, Input, OnInit, QueryList, ViewChild, ViewChildren, AfterViewInit, Renderer2 } from '@angular/core'; export interface ImageSlider { imgUrl: string; link: string; caption: string; } @Component({ selector: 'app-image-slider', templateUrl: './image-slider.component.html', styleUrls: ['./image-slider.component.css'] }) export class ImageSliderComponent implements OnInit, AfterViewInit { @Input() sliders: ImageSlider[] = []; // 获取dom元素 @ViewChild('imageSlider', { static: true }) imgSlider!: ElementRef; // 获取循环出来的dom元素 @ViewChildren('img') imgs!: QueryList<ElementRef>; // eslint-disable-next-line @typescript-eslint/no-empty-function constructor(private rd2: Renderer2) {} // 组件初始化 ngOnInit() { // 对 dom 进行操作 // this.imgSlider.nativeElement.innerHTML = `<span>Hello</span>`; } // 视图完全渲染完成(在这里才能打印出来所有dom元素,在ngOnInit里打印不出来 this.imgs ,因为还没有渲染结束,如果想对dom操作还是在 ngAfterViewInit中操作比较稳妥) ngAfterViewInit(): void { // 原生js方式修改样式 // this.imgs.forEach((item) => { // item.nativeElement.style.height = '100px'; // }); // angular推荐方式修改样式 this.imgs.forEach((item) => { this.rd2.setStyle(item.nativeElement, 'height', '100px'); }); } } ~~~ **dom元素** 的打印结果: ![](https://img.kancloud.cn/92/37/9237c159d10a0c6d70fd751ca5d84b49_618x446.png) >[success] ## 总结 ![](https://img.kancloud.cn/72/01/720155ce39bb9ddb3cd2b7cb4cffe1f3_990x498.png)