Существует три способа использования компонента в приложении Angular.
- Загрузка при изменении маршрута
- Использование в качестве дочернего компонента
- Динамическая загрузка по требованию
Однако эта статья посвящена динамической и ленивой загрузке компонента. Основным преимуществом ленивой загрузки компонента является уменьшение размера начального пакета и загрузка компонента в браузер только при необходимости.
Допустим, у вас есть компонент под названием GreetComponent, как показано в следующем блоке кода,
import { Component, EventEmitter, Input, Output } from '@angular/core';
import { CommonModule } from '@angular/common';
const template = `
<h2>{{message}} </h2>
<button (click)='sendMessage()'>Send Message </button>
`
@Component({
selector: 'app-greet',
standalone: true,
imports: [CommonModule],
template: template
})
export class GreetComponent {
@Input({ required: true }) message?: string;
@Output() messageEvent = new EventEmitter<boolean>();
sendMessage(): void {
this.messageEvent.emit(true);
}
}
Компонент GreetComponent имеет украшенное свойство @Input и украшенный @Output() EvenEmmiter. Компонент FooComponent использует его в качестве дочернего компонента, как показано в следующем блоке кода.
const template = `
<app-greet [message]='message' (messageEvent)='sendMessage($event)'></app-greet>
`
@Component({
selector: 'app-foo',
standalone: true,
imports: [CommonModule,
GreetComponent],
template : template
})
export class FooComponent {
message = "data from parent"
sendMessage(m:boolean){
console.log(m);
}
}
Здесь стоит обратить внимание на несколько моментов,
- GreetComponent является частью массива imports.
- GreetComponent используется в шаблоне.
Из-за этих двух моментов, каждый раз, когда Angular компилирует FooComponent, он также включает GreetComponent, увеличивая размер пакета, содержащего FooComponent.
_Одним из основных преимуществ динамической (ленивой) загрузки компонента является уменьшение размера пакета, поскольку он загружается в браузер только тогда, когда это необходимо. _
Допустим, компонент GreetComponent должен загружаться динамически и лениво при нажатии кнопки в FooComponent. Для этого,
- Добавьте кнопку
- Удалите из шаблона FooComponent
- Удалить GreetComponent из массива импортов. [Важно]
const template = `
<button (click)='loadComponent()'>Load Greet Component </button>
`
@Component({
selector: 'app-foo',
standalone: true,
imports: [CommonModule],
template: template
})
export class FooComponent {
message = "data from parent"
greetcomp: any;
Чтобы динамически загрузить компонент, инжектируйте ViewContainerRef с помощью функции inject или инжекта конструктора.
vcr = inject(ViewContainerRef);
После этого импортируйте файл, содержащий GreetComponent, с помощью оператора import. Оператор import используется в JavaScript для динамической загрузки файла.
const { GreetComponent } = await import(’../greet/greet.component’);
После импорта файла используйте метод CreateComponent в ViewContainerRef.
this.greetcomp = this.vcr.createComponent(GreetComponent);
Вы можете получить доступ ко всем свойствам и событиям динамически загруженных компонентов, используя метод экземпляра. Так, свойству message можно передать значение a, как показано в следующем блоке кода,
this.greetcomp.instance.message = “Hello dynamic Component”;
Вы можете подписаться на EventEmitter, украшенный @Output, как показано далее,
this.greetcomp.instance.messageEvent.subscribe((data:any)=>{
console.log(data);
})
Собрав все вместе, вы можете лениво загрузить GreetComponent нажатием кнопки в FooComponent, как показано в следующем листинге кода,
const template = `
<button (click)='loadComponent()'>Load Greet Component </button>
`
@Component({
selector: 'app-foo',
standalone: true,
imports: [CommonModule],
template: template
})
export class FooComponent {
message = "data from parent"
greetcomp: any;
vcr = inject(ViewContainerRef);
async loadComponent() {
this.vcr.clear();
const { GreetComponent } = await import('../greet/greet.component');
this.greetcomp = this.vcr.createComponent(GreetComponent);
if (this.greetcomp) {
this.greetcomp.instance.message = "Hello dynamic Component";
this.greetcomp.instance.messageEvent.subscribe((data:any)=>{
console.log(data);
})
}
}
}
В настоящее время Angular загружает GreetComponent в конце после всех DOM-элементов FooComponent. Чтобы загрузить его в определенный div-блок, считайте div-блок как ViewChild и ViewConatinerRef. В другом посте я расскажу об этом подробнее.
Надеюсь, эта статья будет вам полезна. Спасибо за прочтение.