Cả hai đều truy vấn các tham chiếu tới các phần tử/component con, nhưng chúng tìm ở những nơi khác nhau: @ViewChild truy vấn template của riêng component, còn truy vấn nội dung được component qua .
Cả hai đều truy vấn các tham chiếu tới các phần tử/component con, nhưng chúng tìm ở những nơi khác nhau: @ViewChild truy vấn template của riêng component, còn truy vấn nội dung được component qua .
@ContentChild<ng-content>@Component({
template: `
<input #nameInput /> <!-- một template reference trong template CỦA TÔI -->
<app-child></app-child>
`,
})
export class ParentComponent implements AfterViewInit {
@ViewChild("nameInput") input!: ElementRef; // theo template ref
@ViewChild(ChildComponent) child!: ChildComponent; // theo kiểu component
ngAfterViewInit() {
this.input.nativeElement.focus(); // có sẵn sau khi VIEW khởi tạo
this.child.doSomething(); // gọi phương thức của một component con
}
}
@ViewChild truy cập các phần tử/component mà chính component đó khai báo trong template của nó — có sẵn trong ngAfterViewInit.
@Component({
selector: "app-card",
template: `<div class="card"><ng-content></ng-content></div>`, // nội dung được chiếu vào đây
})
export class CardComponent implements AfterContentInit {
@ContentChild(CardTitleComponent) title!: CardTitleComponent;
ngAfterContentInit() {
// nội dung được chiếu đã sẵn sàng ở đây (SỚM HƠN ngAfterViewInit)
console.log(this.title);
}
}
<!-- cha chiếu nội dung VÀO app-card -->
<app-card>
<app-card-title>Hello</app-card-title> <!-- đây là thứ ContentChild tìm thấy -->
</app-card>
@ContentChild truy cập nội dung mà cha đã truyền vào (được chiếu qua <ng-content>) — có sẵn trong ngAfterContentInit.
@ViewChild → các phần tử trong template của RIÊNG component này → ngAfterViewInit
@ContentChild → các phần tử ĐƯỢC CHIẾU vào từ cha → ngAfterContentInit
(số nhiều: @ViewChildren / @ContentChildren trả về một QueryList của tất cả các kết quả khớp)
@ViewChildren(ItemComponent) items!: QueryList<ItemComponent>; // tất cả các item khớp
ngAfterViewInit() { this.items.forEach(i => ...); this.items.changes.subscribe(...); }
input = viewChild<ElementRef>("nameInput"); // query dựa trên signal (Angular mới hơn)
Phân biệt @ViewChild (template của bạn) với @ContentChild (nội dung được chiếu) — và thời điểm vòng đời tương ứng của chúng (ngAfterViewInit so với ngAfterContentInit) — là thiết yếu khi xây dựng các component tái sử dụng cần tương tác với hoặc các phần tử template của riêng chúng hoặc nội dung mà người tiêu dùng chiếu vào.
Đây là một điểm nhầm lẫn phổ biến và một nhu cầu thường gặp khi viết các thư viện component, tab, form control, và wrapper phải phối hợp với các phần tử con.
Thư viện câu hỏi phỏng vấn IT với đáp án chi tiết — từ Junior đến Senior.
Ủng hộ