Angular10 컴포넌트 관련 개념을 한 글에서 살펴보겠습니다.
이 글에서는 angular10의 컴포넌트에 대해 소개하고, 컴포넌트 요소, 컴포넌트 수명주기, 컴포넌트 간 통신, 동적 컴포넌트의 기본 사용법을 함께 살펴보겠습니다.
【관련 튜토리얼 추천: "angular tutorial"】
ComponentComponents
- html template
- typescript,behavior 정의
- css 그룹, 여러 CSS 파일을 도입할 수 있으므로 여러 정의 가능 하나의 구성 요소에 CSS 파일
//从angular主模块中引入Component(组件装饰器或组件注解) import { Component } from '@angular/core'; //装饰器中以json的形式声明元数据 @Component({ //它指定了一个叫 <app-root> 的元素。 该元素是 index.html 文件里的一个占位符 //为什么这个组件跟入口index建立了联系呢?因为入口main.ts中绑定了主模块为appModule selector: 'app-root', //在模板中找对应的标签,找到后创建并插入该组件实例 templateUrl: './app.component.html', // html模板 styleUrls: ['./app.component.css'], // css样式,可以引入多个css文件 // 这个属性(内联模板)和templateUrl(外联模板)二选一,template后面可以直接跟html字符串 // 注意在模板语法(反引号)中是使用插值表达式,不能使用${}插入值 template: `<h1>{{title}}</h1>` }) //组件控制器,写逻辑代码的地方 export class AppComponent { title = 'myAngular'; //构造函数可以用来进行属性的声明和初始化语句 //在angular里面有个特别重要的点要记住:只能通过构造函数注入依赖 constructor() {} }
전제 조건
- Angular CLI 설치(npm install -g @angular/cli)
- Angular 프로젝트 만들기(ng new)
이 두 가지 조건이 충족되지 않으면 빌드 환경을 참조하세요.
컴포넌트 생성 방법
Angular CLI를 사용하여 컴포넌트 생성
ng generate component <project-name> // 创建一个组件 ng g c <project-name> // 缩写
컴포넌트 생성에 일반적으로 사용되는 기타 옵션
ng g c <project-name> --skip-tests // 创建一个组件,且不用安装测试文件 ng g c <project-name> --inline-style // 缩写-s,内联样式 ng g c <project-name> --inline-template // 缩写-t,内联模板 ng g c <project-name> --module= <module-name> // 指定创建的组件在哪个模块引用,在多个模块的项目中会用到
Angular CLI를 통해 자동으로 컴포넌트를 생성하는 것 외에도 수동으로 컴포넌트를 생성할 수도 있습니다(권장하지 않음) ), 여기에는 소개가 없습니다.
컴포넌트 라이프사이클(high-level content, master ngOnInit, ngOnDestroy, ngOnChanges, ngAfterViewInit())
작업에서 자주 사용하는 라이프사이클은 ngOninit, ngOnDestroy 2개 뿐이며, 나머지 라이프사이클은 다음과 같습니다. 매우 드물게 사용되지만 구성요소의 수명주기를 마스터할 수 있다면 각도에 대한 더 깊은 이해를 갖게 될 것입니다.
라이프 사이클 의미
컴포넌트 인스턴스의 라이프 사이클은 Angular가 컴포넌트 클래스를 인스턴스화하고 컴포넌트 뷰와 해당 하위 뷰를 렌더링할 때 시작됩니다. 수명 주기에는 항상 변경 감지가 수반되며, 데이터 바인딩된 속성이 변경되면 Angular가 확인하고 필요에 따라 뷰 및 구성 요소 인스턴스를 업데이트합니다. Angular가 구성 요소 인스턴스를 삭제하고 DOM에서 렌더링된 템플릿을 제거하면 수명 주기가 종료됩니다. 지시문은 Angular가 실행 중에 인스턴스를 생성, 업데이트 및 삭제하는 것과 유사한 수명 주기를 갖습니다.
애플리케이션:
앱은 수명 주기 후크 메서드를 사용하여 구성 요소 또는 지시어 수명 주기의 주요 이벤트를 트리거하여 새 인스턴스를 초기화하고, 필요할 때 변경 감지를 시작하고, 변경 감지 중 업데이트에 응답하고, 필요할 때 인스턴스를 삭제할 수 있습니다. .
라이프 사이클 이벤트 구현 방법
모든 구성 요소 또는 지시문은 적절한 시간에 구성 요소 또는 지시문 인스턴스에서 작동할 수 있는 하나 이상의 수명 주기 후크를 구현할 수 있습니다.
각 인터페이스에는 고유한 후크 방법이 있으며 해당 이름은 인터페이스 이름과 ng 접두사로 구성됩니다. 예를 들어 OnInit 인터페이스의 후크 메서드는 ngOnInit()이라고 합니다. 이 메서드를 구성 요소 또는 지시문 클래스에 구현하면 Angular는 먼저 구성 요소 또는 지시문의 입력 속성을 확인한 후 이를 호출합니다.
import { Component } from '@angular/core'; @Component({ selector: 'app-root', styleUrls: ['./app.component.css'], template: `<h1>{{title}}</h1>` }) // 实现OnInit生命周期,可以实现多个生命周期 export class AppComponent implements OnInit{ title = 'myAngular'; constructor() {} ngOnInit(){ console.log("Angular在首次检查完组件的输入属性后,然后调用它,只调用一次") } }
Lifecycle 개요
Hook | Timing | Purpose | Note |
---|---|---|---|
ngOnChanges() | 바인딩된 입력 속성의 값이 변경될 때 호출되며, 첫 번째 호출은 ngOnInit()보다 먼저 발생해야 합니다. | Response 각도일 때 데이터 바인딩된 입력 속성을 설정하거나 재설정합니다. 이 메서드는 현재 및 이전 속성 값의 SimpleChanges 개체를 허용합니다. | 이 일은 매우 자주 발생하므로 여기에서 수행하는 모든 작업은 성능에 큰 영향을 미칩니다. |
ngOnInit() | ngOnChanges()의 첫 번째 라운드가 완료된 후 호출되며 한 번만 호출됩니다. | Angular가 먼저 데이터 바인딩을 표시하고 지시문/구성 요소의 입력 속성을 설정한 후 지시문/구성 요소를 초기화합니다. 컴포넌트가 초기 데이터를 얻기에 좋은 곳입니다 | 변경 감지가 수행될 때마다 ngOnChanges() 직후에, 변경 감지가 수행될 때 ngOnInit() 직후에 한 번만 호출하는 것이 중요합니다 |
ngDoCheck() | 처음으로. | Angular가 자체적으로 감지할 수 없거나 감지할 의사가 없는 변경 사항이 발생하면 감지하고 대응합니다. | ngOnChanges만큼 자주 발생합니다 |
ngAfterContentInit() | 처음 ngDoCheck()가 호출될 때 한 번만. | Angular가 외부 콘텐츠를 구성 요소 뷰 또는 지시어가 있는 뷰에 투영한 후에 호출됩니다. | 한 번만 호출됩니다 |
ngAfterContentChecked() | ngAfterContentInit() 및 각 ngDoCheck() 후에 | Angular가 구성 요소 또는 지시문에 투영된 콘텐츠를 확인할 때마다 호출됩니다. | |
ngAfterViewInit() | ngAfterContentChecked()가 처음 호출될 때 한 번만 호출됩니다. | 구성요소 뷰와 해당 하위 뷰를 초기화한 후 호출됩니다. | 한 번만 호출 |
ngAfterViewChecked() | ngAfterViewInit()하고 ngAfterContentChecked() 이후 매번 호출하세요. | 컴포넌트 뷰와 하위 뷰의 변경 감지를 완료한 후 매번 호출됩니다. | |
ngOnDestroy() | Angular가 지시문/구성 요소를 삭제하기 전에 호출됩니다. | 각 지시문/구성 요소가 Angular에 의해 삭제되기 전에 호출되고 청소됩니다. 메모리 누수를 방지하려면 관찰 가능 항목의 구독을 취소하고 여기에서 이벤트 핸들러를 분리하세요. 관찰 가능한 개체 구독 취소, 타이머 지우기, 이 명령으로 전역적으로 또는 애플리케이션 서비스에 등록된 모든 콜백 등록 취소. | 중요해요 |
重点生命周期详解
初始化组件和指令 ngOnInit
- 在构造函数外部执行复杂的初始化。组件的构造应该既便宜又安全。比如,你不应该在组件构造函数中获取数据。当在测试中创建组件时或者决定显示它之前,你不应该担心新组件会尝试联系远程服务器。ngOnInit() 是组件获取初始数据的好地方。
- 在 Angular 设置好输入属性之后设置组件。构造函数应该只把初始局部变量设置为简单的值。请记住,只有在构造完成之后才会设置指令的数据绑定输入属性。如果要根据这些属性对指令进行初始化,请在运行 ngOnInit() 时设置它们
在实例销毁时进行清理 ngOnDestroy
这里是释放资源的地方,这些资源不会自动被垃圾回收。如果你不这样做,就存在内存泄漏的风险。
- 取消订阅可观察对象和 DOM 事件。
- 停止 interval 计时器。
- 反注册该指令在全局或应用服务中注册过的所有回调。
- ngOnDestroy() 方法也可以用来通知应用程序的其它部分,该组件即将消失
页面埋点
可以在组件中通过ngOnInit和ngOnDestroy方法统计页面的时长,
更好的做法可以通过指令实现ngOnInit和ngOnDestroy生命周期,用来统计页面时长
也可以通过路由守卫来记录页面出入栈所需要的时间
@Directive({selector: '[appSpy]'}) export class SpyDirective implements OnInit, OnDestroy { constructor(private logger: LoggerService) { } ngOnInit() { this.logIt(`onInit`); } ngOnDestroy() { this.logIt(`onDestroy`); } private logIt(msg: string) { this.logger.log(`Spy #${nextId++} ${msg}`); } }
使用变更检测钩子 ngOnchanges
一旦检测到该组件或指令的输入属性发生了变化,Angular 就会调用它的 ngOnChanges() 方法。
因为这个方法会频繁执行,所以要注意判断的计算量,会影响性能。
// 可以监听输入属性的变化 ngOnChanges(changes: SimpleChanges) { for (const propName in changes) { const chng = changes[propName]; const cur = JSON.stringify(chng.currentValue); const prev = JSON.stringify(chng.previousValue); this.changeLog.push(`${propName}: currentValue = ${cur}, previousValue = ${prev}`); } }
组件之间的通信(重要,必须掌握)
一、父子组件的通信(基础)
父传子
1、父组件通过属性绑定向子组件传值
import { Component } from '@angular/core'; @Component({ selector: 'app-parent', template: ` <app-child [msg]="msg"></app-child> ` }) export class ParentComponent { msg = '父组件传的值'; }
2、子组件通过@Input接收数据
import { Component, Input } from '@angular/core'; @Component({ selector: 'app-child', template: ` <p>{{msg}}</p> ` }) export class ChildComponent { @Input() msg: String; }
子传父
1、子组件通过自定义事件,向父组件发送数据
import { Component, Input, EventEmitter, Output} from '@angular/core'; , @Component({ selector: 'app-child', template: ` <p>{{msg}}</p> <button (click)="vote()" >发送</button> ` }) export class ChildComponent { @Input() msg: String; @Output() voted = new EventEmitter<boolean>(); vote() { this.voted.emit("子组件传的值"); } }
2、父组件通过监听自定义事件,接收子组件的传值
import { Component } from '@angular/core'; @Component({ selector: 'app-parent', template: ` <app-child [msg]="msg" (voted)="voted($event)"></app-child> ` }) export class ParentComponent { msg = '父组件传的值'; voted(val){ //监听自定义事件的传值 console.log(val) } }
子组件怎么监听输入属性值的变化?(2种方法)
1、可以使用一个输入属性@Input()的 setter,以拦截父组件中值的变化。
import { Component, Input } from '@angular/core'; @Component({ selector: 'app-child', template: '<h3>"{{name}}"</h3>' }) export class ChildComponent { @Input() get name(): string { return this._name; } set name(name: string) { this._name = (name && name.trim()) || '<no name set>'; } private _name = ''; }
2、通过ngOnChange()来截听输入属性值的变化
当需要监视多个、交互式输入属性的时候,本方法比用属性的 setter 更合适。
import { Component, Input, OnChanges, SimpleChanges } from '@angular/core'; @Component({ selector: 'app-version-child', template: ` <h3>Version {{major}}.{{minor}}</h3> <h4>Change log:</h4> <ul> <li *ngFor="let change of changeLog">{{change}}</li> </ul> ` }) export class VersionChildComponent implements OnChanges { @Input() major: number; @Input() minor: number; changeLog: string[] = []; ngOnChanges(changes: SimpleChanges) { //ngOnchange适合监听子组件多个输入属性的变化 const log: string[] = []; for (const propName in changes) { const changedProp = changes[propName]; const to = JSON.stringify(changedProp.currentValue); if (changedProp.isFirstChange()) { log.push(`Initial value of ${propName} set to ${to}`); } else { const from = JSON.stringify(changedProp.previousValue); log.push(`${propName} changed from ${from} to ${to}`); } } this.changeLog.push(log.join(', ')); } }
父组件怎么读取子组件的属性和调用子组件的方法?(2种方法)
1、通过本地变量代表子组件
父组件不能使用数据绑定来读取子组件的属性或调用子组件的方法。但可以在父组件模板里,新建一个本地变量来代表子组件,然后利用这个变量来读取子组件的属性和调用子组件的方法,如下例所示。
思考:父组件可以通过这种方式读取子组件的私有属性和私有方法吗?
父组件
import { Component } from '@angular/core'; import { CountdownTimerComponent } from './countdown-timer.component'; @Component({ selector: 'app-countdown-parent-lv', template: ` <h3>Countdown to Liftoff (via local variable)</h3> <button (click)="timer.start()">Start</button> //调用子组件方法 <button (click)="timer.stop()">Stop</button> <div class="seconds">{{timer.seconds}}</div> //读取子组件属性 <app-countdown-timer #timer></app-countdown-timer> `, styleUrls: ['../assets/demo.css'] }) export class CountdownLocalVarParentComponent { }
子组件
import { Component, OnDestroy } from '@angular/core'; @Component({ selector: 'app-countdown-timer', template: '<p>{{message}}</p>' }) export class CountdownTimerComponent implements OnDestroy { intervalId = 0; message = ''; seconds = 11; ngOnDestroy() { this.clearTimer(); } start() { this.countDown(); } stop() { this.clearTimer(); this.message = `Holding at T-${this.seconds} seconds`; } private clearTimer() { clearInterval(this.intervalId); } private countDown() { this.clearTimer(); this.intervalId = window.setInterval(() => { this.seconds -= 1; if (this.seconds === 0) { this.message = 'Blast off!'; } else { if (this.seconds < 0) { this.seconds = 10; } // reset this.message = `T-${this.seconds} seconds and counting`; } }, 1000); } }
2、父组件调用@viewChild() (基础,推荐使用)
这个本地变量方法是个简单便利的方法。但是它也有局限性(只能在模板html中使用),因为父组件-子组件的连接必须全部在父组件的模板中进行。父组件本身的ts代码对子组件没有访问权。
当父组件类需要访问子组件时,可以把子组件作为 ViewChild,注入到父组件里面。
父组件类中访问子组件的属性和方法:
import { AfterViewInit, ViewChild } from '@angular/core'; import { Component } from '@angular/core'; import { CountdownTimerComponent } from './countdown-timer.component'; //引入子组件 @Component({ selector: 'app-countdown-parent-vc', template: ` <h3>Countdown to Liftoff (via ViewChild)</h3> <button (click)="start()">Start</button> <button (click)="stop()">Stop</button> <div class="seconds">{{ seconds() }}</div> <app-countdown-timer></app-countdown-timer> `, styleUrls: ['../assets/demo.css'] }) export class CountdownViewChildParentComponent implements AfterViewInit { //通过 @ViewChild 属性装饰器,将子组件 CountdownTimerComponent 注入到私有属性 timerComponent 里面。 @ViewChild(CountdownTimerComponent) private timerComponent: CountdownTimerComponent; seconds() { return 0; } // angular创建了组件的子视图后会调用它,注意获取子组件的属性,要在子组件视图加载之后 ngAfterViewInit() { // 访问子组件属性 setTimeout(() => this.seconds = () => this.timerComponent.seconds, 0); } start() { this.timerComponent.start(); } // 访问子组件的方法 stop() { this.timerComponent.stop(); } }
注意:(使用场景很多,必须掌握)
ngAfterViewInit() 生命周期钩子是非常重要的一步。被注入的计时器组件只有在 Angular 显示了父组件视图之后才能访问,所以它先把秒数显示为 0.
然后 Angular 会调用 ngAfterViewInit 生命周期钩子,但这时候再更新父组件视图的倒计时就已经太晚了。Angular 的单向数据流规则会阻止在同一个周期内更新父组件视图。应用在显示秒数之前会被迫再等一轮。
使用 setTimeout() 来等下一轮,然后改写 seconds() 方法,这样它接下来就会从注入的这个计时器组件里获取秒数的值。
二、组件通过服务来通信(发布订阅者模式,基础,必须掌握)
父组件和它的子组件共享同一个服务,利用该服务在组件家族内部实现双向通信。
不仅局限于父子组件,只要组件与组件共享同一个服务,就可以实现数据通信。
<!--parent.component.html--> <p style="width: 1000px;margin: auto"> <p class="card" style="width: 500px;float: left"> <p class="card-header"> 父组件</p> <p class="card-body"> <h5 class="card-title">父组件</h5> <p class="form-group"> <label for="serviceoutput">父组件服务输入:</label> <input type="text" class="form-control" id="serviceoutput" placeholder="服务输入" [(ngModel)]="serviceInput" > </p> <button class="btn btn-primary" (click)="clickService()">Service方式</button> </p> </p> <app-child></app-child> </p>
<!--child.component.html--> <p class="card" style="width: 500px;"> <p class="card-header">子组件</p> <p class="card-body"> <h5 class="card-title">子组件</h5> <p class="form-group"> <label for="serviceoutput">子组件服务输入:</label> <input type="text" class="form-control" id="serviceoutput" placeholder="服务输入" [(ngModel)]="serviceInput" > </p> <button class="btn btn-primary" (click)="clickService()">Service方式</button> </p> </p>
//服务重点 //meditor.service.ts import {Injectable} from '@angular/core'; import {Subject} from 'rxjs/Subject'; import {Observable} from 'rxjs/Observable'; @Injectable() export class MeditorService { private subject = new Subject<MeditorMsg>(); constructor() {} // 获取订阅者 public getObservable(): Observable<MeditorMsg> { return this.subject.asObservable(); } // 推送信息 public push(msg: MeditorMsg) { this.subject.next(msg); } } // 中间者信息 export interface MeditorMsg { id: string; body: any; }
subscription: Subscription = null; //初始化一个订阅对象 //子组件构造函数,用于监听数据推送 constructor(private meditor: MeditorService) { this.subscription = meditor.getObservable().subscribe( msg => { console.log(msg); if (msg.id === 'parent') { //id为parent,获取父组件数据 this.serviceInput = msg.body; } } ); } // 子组件将数据推送到中间着,给订阅者 clickService() { this.meditor.push({id: 'parent', body: this.serviceInput}); } //父组件构造函数,用于监听数据推送 constructor(private meditor: MeditorService) { this.subscription = meditor.getObservable().subscribe( msg => { console.log(msg); if (msg.id === 'child') { //id为child,获取子组件数据 this.serviceInput = msg.body; } } ); } // 父组件将数据推送到中间着,给订阅者 clickService() { this.meditor.push({id: 'parent', body: this.serviceInput}); } // 注意:订阅一个对象,就是在生命周期结束前,要取消订阅。 ngOnDestroy() { this.subscription.unsubscribe(); }
思考: 这种发布订阅者模式适合全局状态管理吗?
三、可以通过本地缓存来实现通信(Cookie,LocalStorage、SessionStorage)
<!-- catch_namae_type.ts --> // 目的是好维护 // 项目当中用到的页面缓存,需要在这里进行声明;key-value保持一致 // 声明规则,不同类型的缓存使用前缀 session_/ local_ / cookie_ // 动态设置缓存不用在这里声明,但是需要在key后面加'_noSetType_'标识 export const CatchNameType = { session_userInfo: 'session_userInfo', // 用户信息 session_toekn: 'session_token', // token local_loginInfo: 'local_loginInfo', // 本地缓存用户名密码 }; <!--catch.ts--> import { Injectable } from '@angular/core'; // 定义这个类,主要是看全局定义了哪些本地缓存 import { CatchNameType } from './catch_namae_type'; // -------------------------------------------------------缓存工具类(三类方法) // Cookie (方法有:set/get/remove) // SStorage(sessionStorage) (方法有:set/get/remove/clear) // LStorage(localStorage) (方法有:set/get/remove/clear) @Injectable({ providedIn: 'root', }) export class Catch { // cookie public static Cookie = { /** * cookie 存贮 * @param key 属性 * @param value 值 * @param String expire 过期时间,单位天 */ set(key: string, value: any, expire: any): void { if (Catch.is_set_catch_name_type(key)) { const d = new Date(); d.setDate(d.getDate() + expire); document.cookie = `${key}=${value};expires=${d.toDateString()}`; } }, get(key: string): string { const cookieStr = unescape(document.cookie); const arr = cookieStr.split('; '); let cookieValue = ''; // tslint:disable-next-line: prefer-for-of for (let i = 0; i < arr.length; i++) { const temp = arr[i].split('='); if (temp[0] === key) { cookieValue = temp[1]; break; } } return cookieValue; }, remove(key: string): void { document.cookie = `${encodeURIComponent(key)}=;expires=${new Date()}`; }, }; // sessionStorage public static SStorage = { set(key: string, value: any): void { if (Catch.is_set_catch_name_type(key)) { sessionStorage.setItem(key, JSON.stringify(value)); } }, get(key: string): any { const jsonString = sessionStorage.getItem(key) === 'undefined' ? undefined : sessionStorage.getItem(key); return jsonString ? JSON.parse(jsonString) : null; }, remove(key: string): void { sessionStorage.removeItem(key); }, clear(): void { sessionStorage.clear(); }, }; // localStorage public static LStorage = { set(key: string, value: any): void { if (Catch.is_set_catch_name_type(key)) { localStorage.setItem(key, JSON.stringify(value)); } }, get(key: string): any { const jsonString = localStorage.getItem(key) === 'undefined' ? undefined : localStorage.getItem(key); return jsonString ? JSON.parse(jsonString) : null; }, remove(key: string): void { localStorage.removeItem(key); }, clear(): void { localStorage.clear(); }, }; // 设置缓存的时候是否在catch_name_type里面声明 static is_set_catch_name_type(key: string): boolean { let allow = false; // 对动态设置缓存不进行检查 if (key.indexOf('_noSetType_') !== -1) { allow = true; console.log('动态设置缓存', key); return allow; } // 对命名规则进行检查 const nameRule = key.indexOf('session_') !== -1 || key.indexOf('local_') !== -1 || key.indexOf('cookie_') !== -1; if (!nameRule) { allow = false; console.log('命名规则错误', key); return allow; } // 静态设置的缓存需要配置类型 Object.values(CatchNameType).forEach((item) => { if (item === key) { allow = true; } }); if (!allow) { console.log('缓存操作失败,请检查配置缓存类型'); } return allow; } }
四、页面路由传参也可以实现单向通信
这部分内容,我会在路由章节整理。
组件通信总结
所以组件通信大概有如下几种:
1、父子组件通信(1、@Input() @output 2、本地变量#val 3、@viewChild())
2、通过服务
3、页面缓存
4、页面级组件传参(两个页面等同于两个组件)
动态组件
组件的模板不会永远是固定的。应用可能会需要在运行期间按需加载一些新的组件。 通过下面的例子可以了解动态组件的基本使用
1、创建组件,被引入的组件
@Component({ template: `<span>hello world</span>` }) export class DynamicComponent { }
2、创建容器组件,用于加载动态组件
@Component({ selector: 'app-container', template: ` <div #dynamicContainer></div> <button (click)="createComponent()">Create</button> ` }) export class AppContainerComponent { // 声明容器 @ViewChild("dynamicContainer", { read: ViewContainerRef }) container: ViewContainerRef; }
在AppContainerComponent组件中,通过@ViewChild装饰器来获取视图中的模板元素,如果没有指定第二个查询参数,则默认返回 组件实例或相应的DOM元素,但这个示例中,我们需要获取ViewContainerRef实例也就是视图容器。可以在视图容器中创建、插入、删除组件等。
3、动态创建组件
在创建组件之前,需要注入ComponentFactoryResolver服务对象,该服务是动态加载组件的核心,可以将一个组件实例呈现到另一个 组件视图上。
- 使用ComponentFactoryResolve将已声明但未实例化的组件解析成为可以动态加载的component
//依赖组件类型获取对应的factory,从名字上可以看出该factory是用来初始化组件的 const componentFactory = this.ComponentFactoryResolver(DynamicComponent); //调用视图容器的createComponent方法并将组件添加到容器上。该方法内部会调用factory的create方法来初始化组件。 const modalContainerRef = this.container.createComponent(componentFactory);
4、为组件属性赋值
通过如下的方式为组件属性进行赋值
modalContainerRef.instance.property = ***;
5、销毁组件
在使用组件后,记得要销毁组件。
modalContainerRef.destroy();
6、组件注册
为了能够动态创建组件需要将组件在模块的entryComponents中声明。因为在entryComponents中声明的组件Angular都会创建一个 ComponentFactory并将其存储在ComponentFactoryResolver中,这是动态加载必需的步骤。
更多编程相关知识,请访问:编程入门!!
위 내용은 Angular10 컴포넌트 관련 개념을 한 글에서 살펴보겠습니다.의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

AI Hentai Generator
AI Hentai를 무료로 생성하십시오.

인기 기사

뜨거운 도구

메모장++7.3.1
사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전
중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기
강력한 PHP 통합 개발 환경

드림위버 CS6
시각적 웹 개발 도구

SublimeText3 Mac 버전
신 수준의 코드 편집 소프트웨어(SublimeText3)

뜨거운 주제











많은 사용자가 win10에서 일부 게임을 플레이할 때 화면이 멈추거나 화면이 흐려지는 등의 문제에 항상 직면합니다. 이때 다이렉트 플레이 기능을 켜면 문제를 해결할 수 있으며 기능 작동 방법도 매우 간단합니다. 이전 버전의 win10 컴포넌트 다이렉트플레이 설치 방법 1. 검색 상자에 "제어판"을 입력하고 엽니다. 2. 보기 방법으로 큰 아이콘을 선택합니다. 3. "프로그램 및 기능"을 찾습니다. 4. 활성화 또는 활성화하려면 왼쪽을 클릭합니다. Win 기능 끄기 5. 여기에서 이전 버전을 선택하세요. 확인란을 선택하세요.

Vue는 매우 인기 있는 프런트 엔드 프레임워크로, 개발자가 효율적이고 유연하며 유지 관리하기 쉬운 웹 애플리케이션을 구축하는 데 도움이 되는 구성 요소화, 데이터 바인딩, 이벤트 처리 등과 같은 많은 도구와 기능을 제공합니다. 이번 글에서는 Vue를 사용하여 캘린더 컴포넌트를 구현하는 방법을 소개하겠습니다. 1. 요구사항 분석 먼저 이 캘린더 구성요소의 요구사항을 분석해야 합니다. 기본 달력에는 다음과 같은 기능이 있어야 합니다. 이번 달의 달력 페이지를 표시하고 특정 날짜를 클릭하여 이전 달 또는 다음 달로 전환할 수 있도록 지원합니다.

Vue는 현재 가장 인기 있는 프런트엔드 프레임워크 중 하나이며, VUE3은 Vue 프레임워크의 최신 버전입니다. VUE2에 비해 VUE3는 더 높은 성능과 더 나은 개발 경험을 제공하며 많은 개발자의 첫 번째 선택이 되었습니다. VUE3에서는 익스텐트를 사용하여 컴포넌트를 상속하는 것이 매우 실용적인 개발 방법입니다. 이 글에서는 익스텐트를 사용하여 컴포넌트를 상속하는 방법을 소개합니다. 확장이란 무엇입니까? Vue에서 확장은 매우 실용적인 속성으로, 하위 구성 요소가 상위 구성 요소로부터 상속받는 데 사용할 수 있습니다.

Angular 프레임워크의 구성 요소에 대한 기본 표시 동작은 블록 수준 요소에 대한 것이 아닙니다. 이 디자인 선택은 구성 요소 스타일의 캡슐화를 촉진하고 개발자가 각 구성 요소가 표시되는 방법을 의식적으로 정의하도록 장려합니다. CSS 속성 표시를 명시적으로 설정하면 Angular 구성 요소의 표시를 완전히 제어하여 원하는 레이아웃과 응답성을 얻을 수 있습니다.

Win10 이전 버전 구성요소는 일반적으로 기본적으로 닫혀 있으므로 사용자가 직접 설정해야 합니다. 먼저 작업은 아래 단계를 따르기만 하면 됩니다. 1. 시작을 클릭한 다음 "Win 시스템"을 클릭합니다. 2. 클릭하여 제어판으로 들어갑니다. 3. 그런 다음 아래 프로그램을 클릭합니다. 4. "Win 기능 활성화 또는 끄기"를 클릭합니다. 5. 여기에서 원하는 것을 선택할 수 있습니다. 열기 위해

Vue는 JSX를 통해 어떻게 구성 요소를 동적으로 렌더링합니까? 다음 기사에서는 Vue가 JSX를 통해 구성 요소를 효율적으로 동적으로 렌더링하는 방법을 소개합니다. 도움이 되기를 바랍니다.

VSCode에서 Vue/React 구성 요소를 개발할 때 구성 요소를 실시간으로 미리 보는 방법은 무엇입니까? 이 기사에서는 VSCode의 Vue/React 구성 요소를 실시간으로 미리 볼 수 있는 플러그인을 공유하겠습니다. 도움이 되기를 바랍니다.

Vue 컴포넌트 실습: 페이징 컴포넌트 개발 소개 웹 애플리케이션에서 페이징 기능은 필수 컴포넌트입니다. 좋은 페이지 매김 구성 요소는 표현이 간단하고 명확해야 하며, 기능이 풍부하고, 통합 및 사용이 쉬워야 합니다. 이 기사에서는 Vue.js 프레임워크를 사용하여 고도로 사용자 정의 가능한 페이징 구성 요소를 개발하는 방법을 소개합니다. Vue 컴포넌트를 활용하여 개발하는 방법을 코드 예시를 통해 자세히 설명하겠습니다. 기술 스택 Vue.js2.xJavaScript(ES6) HTML5 및 CSS3 개발 환경
