جاوااسکریپت - چگونه از ViewChild به درستی استفاده کنیم


این برنامه Angular تنها از کامپوننت app-root تشکیل شده است که شامل یک <div> و یک <button> میباشد.

وقتی یک دکمه کلیک میشود، تابع onClick() شی div_a را با موارد زیر در کنسول ثبت میکند:

console.log("...onClick() div_a:", this.div_a);

با div_a تعریفشده با دستور زیر:

@ViewChild('div_a', { static: false }) div_a: Component;

سوال: چرا هر دو تابع ngOnInit و constructor لاگ میکنند که div_a تعریف نشده است؟ چگونه میتوان مشکل عدم توانایی این توابع در استفاده از شیء div_a را برطرف کرد؟

در زیر لینک پروژه Stackblitz آمده است (لطفاً توجه داشته باشید که شاخه GitHub که به این پروژه stackblitz متصل است نیاز دارد از شاخه master به شاخه qViewChild تغییر داده شود).

https://stackblitz.com/edit/angular-r9hwbs?file=src%2Fapp%2Fwidget-a%2Fwidget-a.component.html

پاسخ شماره ۱

بر اساس مستندات، پرس و جوهای ViewChild و ViewChildren قبل از AfterViewInit اجرا میشوند، بنابراین شما باید به آنها در آنجا دسترسی پیدا کنید. فقط دسترسی به div_a کار نخواهد کرد مگر اینکه آن را در قالب علامتگذاری کنید.

از جمله دیگران، کودکانی که میتوانید به آنها دسترسی داشته باشید عبارتند از:

  • هر کلاسی با دکوراتور @Component یا @Directive
  • یک متغیر مرجع قالب به صورت رشته (مثلاً query <my-component #cmp></my-component> با @ViewChild('cmp'))

پس شما به چیزی شبیه به این نیاز خواهید داشت:

<p #myPara>
  Start editing to see some magic happen :)
</p>
import { Component, ViewChild, AfterViewInit } from '@angular/core';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent implements AfterViewInit  {
  @ViewChild('myPara', {static: false}) paragraph;


  ngAfterViewInit() {
    console.log(this.paragraph) // results in -> ElementRef {nativeElement: p}
  }
}

حمله برقآسا

پاسخ شماره ۲

هنگام استفاده از @ViewChild از ngOnInit یا constructor استفاده نکنید زیرا هنوز بارگذاری نشده است. از ngAfterViewInit() استفاده کنید.