Как использовать ViewChild в Angular для доступа к дочернему компоненту, директиве или элементу DOM
Введение
Эта статья познакомит вас с декоратором Angular ViewChild
.
Могут быть ситуации, когда вы хотите получить доступ к директиве, дочернему компоненту или элементу DOM из класса родительского компонента. Декоратор ViewChild
возвращает первый элемент, соответствующий заданной директиве, компоненту или селектору ссылки на шаблон.
Предпосылки
Если вы хотите следовать этому руководству:
- Рассмотрите возможность установки
@angular/cli
. - Используйте
@angular/cli
, чтобы создать новый проект для тестирования функциональностиViewChild
.
Это руководство было проверено с помощью @angular/core
v13.0.2 и @angular/cli
v13.0.3.
Использование ViewChild с директивами
ViewChild
позволяет получить доступ к директивам.
Допустим, у вас есть SharkDirective
. Эта директива будет искать элементы с атрибутом appShark
и добавлять к тексту элемента слово Shark
.
В идеале вы будете использовать @angular/cli
для генерации
вашей директивы:
- ng generate directive shark --skip-tests
Эта команда создаст файл shark.directive.ts
. И добавляет директиву в app.module.ts
:
import { SharkDirective } from './shark.directive';
...
@NgModule({
declarations: [
AppComponent,
SharkDirective
],
...
})
Затем используйте ElementRef
и Renderer2
, чтобы переписать текст. Замените содержимое shark.directive.ts
следующим:
import {
Directive,
ElementRef,
Renderer2
} from '@angular/core';
@Directive(
{ selector: '[appShark]' }
)
export class SharkDirective {
creature = 'Dolphin';
constructor(elem: ElementRef, renderer: Renderer2) {
let shark = renderer.createText('Shark ');
renderer.appendChild(elem.nativeElement, shark);
}
}
Затем добавьте атрибут appShark
в span
, содержащий текст в шаблоне компонента. Замените содержимое app.component.html
следующим:
<span appShark>Fin!</span>
При просмотре приложения в браузере оно отобразит слово Shark
перед содержимым элемента:
OutputShark Fin!
Теперь вы также можете получить доступ к переменной экземпляра creature
в SharkDirective
и установить переменную экземпляра extraCreature
с ее значением. Замените содержимое app.component.ts
следующим:
import {
Component,
ViewChild,
AfterViewInit
} from '@angular/core';
import { SharkDirective } from './shark.directive';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements AfterViewInit {
extraCreature!: string;
@ViewChild(SharkDirective)
set appShark(directive: SharkDirective) {
this.extraCreature = directive.creature;
};
ngAfterViewInit() {
console.log(this.extraCreature); // Dolphin
}
}
Этот код использовал сеттер для установки переменной extraCreature
. Обратите внимание, что он ожидает, пока хук жизненного цикла AfterViewInit
получит доступ к переменной, так как именно тогда становятся доступными дочерние компоненты и директивы.
При просмотре приложения в браузере вы по-прежнему будете видеть сообщение Акулий плавник!
. Однако в журнале консоли будет отображаться:
OutputDolphin
Родительский компонент смог получить доступ к значению из директивы.
Использование ViewChild с элементами DOM
ViewChild
позволяет получить доступ к собственным элементам DOM, у которых есть ссылочная переменная шаблона.
Допустим, у вас есть <input>
в шаблоне со ссылочной переменной #someInput
. Замените содержимое app.component.html
следующим:
<input #someInput placeholder="Your favorite sea creature">
Теперь вы можете получить доступ к <input>
с помощью ViewChild
и установить value
. Замените содержимое app.component.ts
следующим:
import {
Component,
ViewChild,
AfterViewInit,
ElementRef
} from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements AfterViewInit {
@ViewChild('someInput') someInput!: ElementRef;
ngAfterViewInit() {
this.someInput.nativeElement.value = 'Whale!';
}
}
Когда ngAfterViewInit
срабатывает, значение <input>
будет установлено на:
OutputWhale!
Родительский компонент смог установить значение дочернего элемента DOM.
Использование ViewChild с дочерними компонентами
ViewChild
позволяет получить доступ к дочернему компоненту и вызвать методы или получить доступ к переменным экземпляра, которые доступны дочернему компоненту.
Допустим, у вас есть PupComponent
.
В идеале вы будете использовать @angular/cli
для генерации
вашего компонента:
- ng generate component pup --flat --skip-tests
Эта команда создаст файлы pup.component.ts
, pup.component.css
и pup.component.html
. И добавляет компонент в app.module.ts
:
import { PupComponent } from './pup.component';
...
@NgModule({
declarations: [
AppComponent,
PupComponent
],
...
})
Затем добавьте метод whoAmI
в PupComponent
, который возвращает сообщение:
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-pup',
templateUrl: './pup.component.html',
styleUrs: ['./pup/component.css']
})
export class PupComponent implements OnInit {
constructor() { }
whoAmI() {
return 'I am a pup component!';
}
ngOnInit(): void {
}
}
Затем укажите ссылку на дочерний компонент в шаблоне приложения. Замените содержимое app.component.html
следующим:
<app-pup>pup works!</app-pup>
Теперь вы можете вызвать метод whoAmI
из класса родительского компонента с помощью ViewChild
. Замените содержимое app.component.ts
следующим:
import {
Component,
ViewChild,
AfterViewInit
} from '@angular/core';
import { PupComponent } from './pup.component';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
})
export class AppComponent implements AfterViewInit {
@ViewChild(PupComponent) pup!: PupComponent;
ngAfterViewInit() {
console.log(this.pup.whoAmI()); // I am a pup component!
}
}
При просмотре приложения в браузере в журнале консоли будет отображаться:
OutputI am a pup component!
Родительский компонент смог вызвать метод whoAmI
дочернего компонента.
Заключение
В этом руководстве вы использовали ViewChild
для доступа к директиве, дочернему компоненту и элементу DOM из класса родительского компонента.
Если ссылка изменяется на новый элемент динамически, ViewChild
автоматически обновит свою ссылку.
В случаях, когда вы хотите получить доступ к нескольким дочерним элементам, вместо этого вы должны использовать ViewChildren
.
Если вы хотите узнать больше об Angular, ознакомьтесь с нашей темой по Angular, где вы найдете упражнения и проекты по программированию.