Разница между Конструктором и ngOnInit

1075

Angular предоставляет хук жизненного цикла ngOnInitпо умолчанию.

Зачем ngOnInitиспользовать, если у нас уже есть constructor?

Хасина П.А.
источник
11
эй, посмотрите мой ответ, который объясняет разницу с точки зрения внутренней работы Angular
Макс Корецкий
2
проверить статью Существенная разница между Constructor и ngOnInit в Angular
Макс Корецкий,
1
@MaximKoretskyi, ваша ссылка мертва.
Яш Капур

Ответы:

1112

Метод Constructorпо умолчанию для класса, который выполняется при создании экземпляра класса и обеспечивает правильную инициализацию полей в классе и его подклассах. Angular, или лучше Dependency Injector (DI), анализирует параметры конструктора и, когда он создает новый экземпляр, вызывая new MyClass()его, пытается найти поставщиков, соответствующих типам параметров конструктора, разрешает их и передает их конструктору, например

new MyClass(someArg);

ngOnInit это хук жизненного цикла, вызываемый Angular для указания того, что Angular завершил создание компонента.

Мы должны импортировать OnInitкак это, чтобы использовать его (фактически реализация OnInitне обязательна, но считается хорошей практикой):

import { Component, OnInit } from '@angular/core';

Затем, чтобы использовать make нас из метода OnInit, мы должны реализовать класс следующим образом:

export class App implements OnInit {
  constructor() {
     // Called first time before the ngOnInit()
  }

  ngOnInit() {
     // Called after the constructor and called  after the first ngOnChanges() 
  }
}

Реализуйте этот интерфейс для выполнения пользовательской логики инициализации после инициализации связанных с данными свойств вашей директивы. ngOnInit вызывается сразу после того, как привязанные к данным свойства директивы были проверены впервые, и до того, как был проверен любой из его дочерних элементов. Он вызывается только один раз, когда создается директива.

В основном мы используем ngOnInitдля всей инициализации / объявления и избегаем вещей для работы в конструкторе. Конструктор должен использоваться только для инициализации членов класса, но не должен выполнять фактическую «работу».

Таким образом, вы должны использовать constructor()для установки Dependency Injection, а не многое другое. ngOnInit () - лучшее место для «запуска» - это где / когда разрешаются привязки компонентов.

Для получения дополнительной информации обратитесь сюда:

Пардип Джейн
источник
62
Точно, большинство (или даже все) языков, основанных на классах, имеют конструкторы для обеспечения надлежащего порядка инициализации, особенно классов, которые расширяют другие классы, где могут возникать некоторые довольно сложные проблемы, такие как конечные поля (не знаю, есть ли в TS) и тому подобное. Контракторы не связаны с Angular2, они являются функцией TypeScript. Перехватчики жизненного цикла вызываются Angular после некоторой инициализации или когда происходит какое-то событие, чтобы позволить компоненту воздействовать на определенные ситуации и дать ему возможность выполнять некоторые задачи в нужное время.
Гюнтер Цохбауэр
13
В angular.io/docs/ts/latest/guide/server-communication.html есть кавычка, которая также объясняет это: «Компоненты легче тестировать и отлаживать, когда их конструкторы просты, и все это реально работает (особенно вызывая удаленный сервер) обрабатывается отдельным способом. " - В этом случае этот метод является ngOnInit ()
yoonjesung
3
является ловушкой жизненного цикла, вызываемой Angular2, чтобы указать, что Angular завершил создание компонента. - это не совсем так. он сигнализирует, что инициализировал привязки. Компонент создан ранее. Смотрите мой ответ
Макс Корецкий
22
Как и во всех «лучших практиках», я думаю, что было бы неплохо также объяснить, почему вы не должны выполнять «работу» в конструкторе. Эта статья под руководством команды Angular плотная, но может помочь: misko.hevery.com/code-reviewers-guide/… Кроме того, следует меньше обращать внимание на заклинания, необходимые для реализации OnInit (это легко найти), и больше на критический факт, что привязки данных не доступны в конструкторе.
Рейким
2
Если строгий режим имеет значение true в tsconfig.jsonfile like "strict": true, то вы должны инициализировать членов класса в constructor, а не в ngOnitlike FormGroup.
Рохит Шарма
174

В статье Существенное различие между Constructor и ngOnInit в Angular исследует разницу с разных точек зрения. Этот ответ дает наиболее важное объяснение различий, связанных с процессом инициализации компонента, которое также показывает различия в использовании.

Угловой процесс начальной загрузки состоит из двух основных этапов:

  • построение дерева компонентов
  • обнаружение изменения хода

Конструктор компонента вызывается, когда Angular создает дерево компонентов. Все хуки жизненного цикла вызываются как часть обнаружения изменений во время работы.

Когда Angular конструирует дерево компонентов, инжектор корневого модуля уже настроен, поэтому вы можете внедрить любые глобальные зависимости. Кроме того, когда Angular создает экземпляр класса дочернего компонента, инжектор для родительского компонента также уже настроен, поэтому вы можете внедрить поставщиков, определенных в родительском компоненте, включая сам родительский компонент. Компонентные конструкторы - это единственный метод, который вызывается в контексте инжектора, поэтому, если вам нужна какая-либо зависимость, это единственное место, где можно получить эти зависимости.

Когда Angular начинает обнаружение изменений, создается дерево компонентов и вызывались конструкторы для всех компонентов в дереве. Также узлы шаблона каждого компонента добавляются в DOM. Механизм @Inputсвязи обрабатывается во время обнаружения изменений, поэтому нельзя ожидать, что свойства будут доступны в конструкторе. Это будет доступно после ngOnInit.

Давайте посмотрим на быстрый пример. Предположим, у вас есть следующий шаблон:

<my-app>
   <child-comp [i]='prop'>

Итак, Angular начинает загрузку приложения. Как я уже сказал, сначала создаются классы для каждого компонента. Так он называет MyAppComponentконструктор. Он также создает узел DOM, который является хост-элементом my-appкомпонента. Затем он переходит к созданию элемента хоста для child-compи вызывающего ChildComponentконструктора. На данном этапе это на самом деле не касается iпривязки ввода и каких-либо хуков жизненного цикла. Поэтому, когда этот процесс завершится, Angular получит следующее дерево представлений компонентов:

MyAppView
  - MyApp component instance
  - my-app host element data
       ChildCompnentView
         - ChildComponent component instance
         - child-comp host element data  

Только после этого запускает обнаружение изменений и обновляет привязки для my-appвызовов и ngOnInitв классе MyAppComponent. Затем он переходит к обновлению привязок для child-compвызовов и ngOnInitв классе ChildComponent.

Вы можете сделать свою логику инициализации либо в конструкторе, либо в ngOnInitзависимости от того, что вам нужно. Например, статья Вот как получить ViewContainerRef до оценки запроса @ViewChild, показывает, какой тип логики инициализации может потребоваться выполнить в конструкторе.

Вот несколько статей, которые помогут вам лучше понять тему:

Макс Корецкий
источник
33
это должен быть принятый ответ. это фактически объясняет ПОЧЕМУ, а не повторение мантр и констатацию the constructor should only be used to inject dependencies.
Ставм
1
@ yannick1976, спасибо! Ознакомьтесь со ссылками на статьи
Макс Корецкий
@flobacca, не могли бы вы перефразировать вопрос, трудно понять, о чем вы спрашиваете
Макс Корецкий,
Пожалуйста, поправьте меня, если я ошибаюсь. Я понял, что сначала создается дерево компонентов, а затем меняется процесс обнаружения. Вы написали, что сначала вызывается конструктор AppComponent (вместе с разрешенными зависимостями), затем вызывается конструктор ChildComponent (вместе с зависимостями), затем вызывается привязка Input для AppComponent и затем OnInit. Но меня беспокоит, если я добавлю хуки жизненного цикла к обоим компонентам, поток будет AppComponentConstructor - -> AppComponentOnInit - → ChildComponentConstructor - → ChildComponentOnInit Почему AppComponentOnInit вызывается раньше ChildComponentConstructor
user2485435
1
@MaxKoretskyiakaWizard ты был прав. Я сделал ошибку в настройке приложения. это работает как описано вами. angular-c7zjsx.stackblitz.io
user2485435
96

Я думаю, что лучшим примером будет использование услуг. Допустим, я хочу получить данные с моего сервера, когда мой компонент активирован. Допустим, я также хочу сделать некоторые дополнительные действия с данными после того, как получу их с сервера, возможно, я получу ошибку и захочу зарегистрировать их по-другому.

Это действительно просто с ngOnInit поверх конструктора, это также ограничивает количество слоев обратного вызова, которые мне нужно добавить в мое приложение.

Например:

export class Users implements OnInit{

    user_list: Array<any>;

    constructor(private _userService: UserService){
    };

    ngOnInit(){
        this.getUsers();
    };

    getUsers(){
        this._userService.getUsersFromService().subscribe(users =>  this.user_list = users);
    };


}

с моим конструктором я мог бы просто вызвать свой _userService и заполнить свой user_list, но, возможно, я хочу сделать с ним некоторые дополнительные вещи. Например, убедитесь, что все в верхнем регистре, и я не совсем уверен, как поступают мои данные.

Так что намного проще использовать ngOnInit.

export class Users implements OnInit{

    user_list: Array<any>;

    constructor(private _userService: UserService){
    };

    ngOnInit(){
        this.getUsers();
    };

    getUsers(){
        this._userService.getUsersFromService().subscribe(users =>  this.user_list = users);
        this.user_list.toUpperCase();
    };


}

Это намного легче увидеть, и поэтому я просто вызываю свою функцию внутри моего компонента при инициализации вместо того, чтобы искать его где-то еще. На самом деле это просто еще один инструмент, который вы можете использовать, чтобы его было легче читать и использовать в будущем. Также я считаю очень плохой практикой помещать вызовы функций в конструктор!

Морган Г
источник
Ваш пример может быть упрощен, если вы просто установите user_list в Observable. Angular2 имеет асинхронный канал, поэтому проблем не возникнет.
DarkNeuron
@Morgan, только для того, чтобы я кое-что узнал здесь, почему вы сначала создаете функцию, getUsersа затем вставляете ее в ngOnInit? Разве это не меньше кода, чтобы просто написать его в ngOnInit? Мне просто интересно, почему люди так делают? Вы можете повторно использовать код, если хотите? Спасибо.
Альфа Браво
31
Как видно из ответа ниже, это не имеет значения, если оно в конструкторе. Это не реальный ответ на цель.
Джимми Кейн
8
Я не вижу, как это отвечает на вопрос вообще. Почему ты не можешь просто вставить код в constructor?
CodyBugstein
1
@Morgan, почему ты не можешь просто сделатьconstructor(private _userService: UserService){ this.getUsers(); };
Эшли
82

Хорошо, в первую очередь ngOnInitэто часть жизненного цикла Angular , а также constructorчасть класса JavaScript ES6 , так что основное отличие начинается прямо здесь! ...

Посмотрите на диаграмму ниже, которую я создал, которая показывает жизненный цикл Angular.

ngOnInit против конструктора

В Angular2 + мы используем constructorэто DI(Dependency Injection)для нас, в то время как в Angular 1 это происходило посредством вызова метода String и проверки, какая зависимость была введена.

Как вы видите на приведенной выше диаграмме, ngOnInitэто происходит после того, как конструктор будет готов ngOnChnagesи будет запущен после того, как компонент будет готов для нас. На этом этапе может произойти вся инициализация, простой пример - внедрение службы и инициализация ее при инициализации.

Хорошо, я также поделился примером кода, который вы можете посмотреть, посмотреть, как мы его используем, ngOnInitи constructorв приведенном ниже коде:

import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';


@Component({
 selector: 'my-app',
 template: `<h1>App is running!</h1>
  <my-app-main [data]=data></<my-app-main>`,
  styles: ['h1 { font-weight: normal; }']
})
class ExampleComponent implements OnInit {
  constructor(private router: Router) {} //Dependency injection in the constructor

  // ngOnInit, get called after Component initialised! 
  ngOnInit() {
    console.log('Component initialised!');
  }
}
Алиреза
источник
1
Спасибо. это должен быть лучший ответ.
Дон Диланга
58

Первый (конструктор) связан с созданием класса и не имеет ничего общего с Angular2. Я имею в виду, что конструктор можно использовать в любом классе. Вы можете поместить в него некоторую обработку инициализации для вновь созданного экземпляра.

Второй соответствует хуку жизненного цикла компонентов Angular2:

Цитируется с официального сайта angular:

  • ngOnChanges вызывается при изменении значения привязки ввода или вывода
  • ngOnInit называется после первого ngOnChanges

Поэтому вы должны использовать, ngOnInitесли обработка инициализации опирается на привязки компонента (например, параметры компонента, определенные с помощью @Input), в противном случае конструктора будет достаточно ...

Тьерри Темплиер
источник
49

Я просто добавлю одну важную вещь, которая была пропущена в объяснениях выше и объясняет, когда вы ДОЛЖНЫ использоватьngOnInit .

Если вы делаете какие-либо манипуляции с DOM компонента с помощью, например, ViewChildren , ContentChildren или ElementRef , ваши собственные элементы не будут доступны на этапе конструктора.

Тем не менее, поскольку это ngOnInitпроисходит после того, как компонент был создан и ngOnChangesбыл вызван check ( ), вы можете получить доступ к DOM на этом этапе.

export class App implements OnInit, AfterViewInit, AfterContentInit {
  @Input() myInput: string;
  @ViewChild() myTemplate: TemplateRef<any>;
  @ContentChild(ChildComponent) myComponent: ChildComponent; 

  constructor(private elementRef: ElementRef) {
     // this.elementRef.nativeElement is undefined here
     // this.myInput is undefined here
     // this.myTemplate is undefined here
     // this.myComponent is undefine here
  }

  ngOnInit() {
     // this.elementRef.nativeElement can be used from here on
     // value of this.myInput is passed from parent scope
     // this.myTemplate and this.myComponent are still undefined
  }
  ngAfterContentInit() {
     // this.myComponent now gets projected in and can be accessed
     // this.myTemplate is still undefined
  }

  ngAfterViewInit() {
     // this.myTemplate can be used now as well
  }
}
Мирослав Йонас
источник
3
Нет. В @ViewChildrenчастности, вам нужно использовать ngAfterViewInitметод. Смотрите здесь: stackoverflow.com/questions/46314734/…
AsGoodAsItGets
1
Спасибо, @AsGoodAsItGets за указание на это. Теперь я улучшил ответ
Мирослав Йонас
38

Короткий и простой ответ будет:

Constructor: constructorявляется прогономdefault method ( по умолчанию ) при создании компонента. Когда вы создаете an instanceкласс, это время также constructor(default method)будет вызвано. Другими словами, когда вызывается компонент и вызывается constructed or/and an instance is created constructor(default method)соответствующий код, написанный внутри. В основном и обычно в Angular2него вводят такие вещи, как servicesкогда компонент строится для дальнейшего использования.

OnInit: ngOnInit - это хук жизненного цикла компонента, который запускается первым после constructor(default method) инициализации компонента.

Итак, Ваш конструктор будет вызываться первым, а Oninit будет вызываться позже после метода конструктора.

boot.ts

import {Cmomponent, OnInit} from 'angular2/core';
import {ExternalService} from '../externalService';

export class app implements OnInit{
   constructor(myService:ExternalService)
   {
           this.myService=myService;
   }

   ngOnInit(){
     // this.myService.someMethod() 
   }
}

Ресурсы: крючок LifeCycle

Вы можете проверить это небольшое демо, которое показывает реализацию обеих вещей.

micronyks
источник
5
Я думаю, что «конструктор - это то, что запускается или вызывается при инициализации компонента». вводит в заблуждение. Конструктор - это особенность класса, а не компонента. Я бы сказал, что экземпляр класса становится компонентом только после вызова конструктора, а Angular выполнил его инициализацию.
Гюнтер Цохбауэр
Да, изменил заявление, которое вы можете проверить сейчас.
Микроникс
1
Хм, ИМХО, это все тот же "конструктор (метод по умолчанию) - это то, что запускается или вызывается при создании компонента". Он вызывается не только при создании компонента, но и для служб или когда new MyClass()выполняется подобный код . Я думаю, что вводить в заблуждение утверждение о компонентах, о классах и инициализации экземпляров этих классов. Компонент просто оказывается таким классом. В противном случае я думаю, что это хороший ответ.
Гюнтер Цохбауэр
2
Да, конечно. Забыл упомянуть, что когда вы создаете объект класса, это время также constructorвызывается. Но этот ответ был написан в контексте angular2. Чтобы узнать лучший ответ, вы должны знать основы ООП. Еще я обновлю ответ.
Микроникс
@ GünterZöchbauer, я не думаю, что это правильное утверждение, которое является особенностью класса, а не компонента . С точки зрения языка программирования да, это правильно. Но я могу успешно работать с компонентами без каких-либо ловушек жизненного цикла вообще. Но я не могу работать с компонентом без конструктора, если мне нужен DI, потому что это единственное место для инъекций. Смотрите мой ответ
Макс Корецкий
20

Как и во многих других языках, вы можете инициализировать переменные на уровне класса, конструктора или метода. Разработчик должен решить, что лучше в их конкретном случае. Но ниже приведен список лучших практик, когда дело доходит до принятия решения.

Переменные уровня класса

Обычно вы объявляете здесь все свои переменные, которые будут использоваться в остальных компонентах. Вы можете инициализировать их, если значение не зависит от чего-либо еще, или использовать ключевое слово const для создания констант, если они не изменятся.

export class TestClass{
    let varA: string = "hello";
}

Конструктор

Обычно лучше не делать ничего в конструкторе, а просто использовать его для классов, которые будут внедрены. Большую часть времени ваш конструктор должен выглядеть так:

   constructor(private http: Http, private customService: CustomService) {}

это автоматически создаст переменные уровня класса, так что у вас будет доступ customService.myMethod()без необходимости делать это вручную.

NgOnInit

NgOnit - это хук жизненного цикла, предоставляемый платформой Angular 2. Ваш компонент должен быть реализован OnInit, чтобы использовать его. Этот хук жизненного цикла вызывается после вызова конструктора и инициализации всех переменных. Большая часть вашей инициализации должна идти сюда. У вас будет уверенность, что Angular правильно инициализировал ваш компонент, и вы можете начать делать любую логику, которая вам нужнаOnInit вместо того, чтобы делать вещи, когда ваш компонент не завершил загрузку должным образом.

Вот изображение, детализирующее порядок того, что называется:

введите описание изображения здесь

https://angular.io/docs/ts/latest/guide/lifecycle-hooks.html

TLDR

Если вы используете платформу Angular 2 и вам нужно взаимодействовать с определенными событиями жизненного цикла, используйте методы, предоставленные для этого, чтобы избежать проблем.

Эдуардо Деннис
источник
19

Чтобы проверить это, я написал этот код, заимствуя урок по NativeScript :

user.ts

export class User {
    email: string;
    password: string;
    lastLogin: Date;

    constructor(msg:string) {        
        this.email = "";
        this.password = "";
        this.lastLogin = new Date();
        console.log("*** User class constructor " + msg + " ***");
    }

    Login() {
    }
}

login.component.ts

import {Component} from "@angular/core";
import {User} from "./../../shared/user/user"

@Component({
  selector: "login-component",
  templateUrl: "pages/login/login.html",
  styleUrls: ["pages/login/login-common.css", "pages/login/login.css"]
})
export class LoginComponent {

  user: User = new User("property");  // ONE
  isLoggingIn:boolean;

  constructor() {    
    this.user = new User("constructor");   // TWO
    console.log("*** Login Component Constructor ***");
  }

  ngOnInit() {
    this.user = new User("ngOnInit");   // THREE
    this.user.Login();
    this.isLoggingIn = true;
    console.log("*** Login Component ngOnInit ***");
  }

  submit() {
    alert("You’re using: " + this.user.email + " " + this.user.lastLogin);
  }

  toggleDisplay() {
    this.isLoggingIn = !this.isLoggingIn;
  }

}

Консольный вывод

JS: *** User class constructor property ***  
JS: *** User class constructor constructor ***  
JS: *** Login Component Constructor ***  
JS: *** User class constructor ngOnInit ***  
JS: *** Login Component ngOnInit ***  
abbaf33f
источник
18

Основное различие между конструктором и тем ngOnInit, что ngOnInitэто ловушка жизненного цикла и запускается после конструктора. Шаблон интерполированного компонента и входные начальные значения недоступны в конструкторе, но они доступны вngOnInit .

Практическая разница заключается в том, как ngOnInitвлияет структура кода. Большая часть кода инициализации может быть перемещена в ngOnInit- если это не создает условия гонки .

Конструктор антипаттерн

Значительный объем кода инициализации затрудняет расширение, чтение и тестирование метода конструктора.

Обычный рецепт отделения логики инициализации от конструктора класса - переместить его в другой метод, например init:

class Some {
  constructor() {
    this.init();
  }

  init() {...}
}

ngOnInit Может служить этой цели в компонентах и ​​директивах:

constructor(
  public foo: Foo,
  /* verbose list of dependencies */
) {
  // time-sensitive initialization code
  this.bar = foo.getBar();
}

ngOnInit() {
  // rest of initialization code
}

Внедрение зависимости

Основная роль конструкторов классов в Angular - это внедрение зависимостей. Конструкторы также используются для аннотации DI в TypeScript. Почти все зависимости присваиваются как свойства экземпляру класса.

Средний компонент / конструктор директивы уже достаточно большой, потому что он может иметь многострочную сигнатуру из-за зависимостей, добавляя ненужную логику инициализации в тело конструктора, что вносит вклад в антипаттерн.

Асинхронная инициализация

Конструктор асинхронной инициализации часто можно считать антипаттерном и иметь запах, потому что создание экземпляра класса заканчивается раньше, чем асинхронная процедура, и это может создать условия гонки. Если это не так, ngOnInitи другие ловушки жизненного цикла - лучшие места для этого, особенно потому что они могут извлечь выгоду из asyncсинтаксиса:

constructor(
  public foo: Foo,
  public errorHandler: ErrorHandler
) {}

async ngOnInit() {
  try {
    await this.foo.getBar();
    await this.foo.getBazThatDependsOnBar();
  } catch (err) {
    this.errorHandler.handleError(err);
  }
}

Если существуют условия гонки (включая то, что компонент не должен появляться при ошибке инициализации), процедура асинхронной инициализации должна выполняться перед созданием экземпляра компонента и перемещаться в родительский компонент, защиту маршрутизатора и т. Д.

Модульное тестирование

ngOnInitявляется более гибким, чем конструктор, и предоставляет некоторые преимущества для модульного тестирования, которые подробно описаны в этом ответе .

Учитывая, что ngOnInitэто не вызывается автоматически при компиляции компонентов в модульных тестах, вызываемые методы ngOnInitмогут быть шпионскими или поддельными после создания экземпляра компонента.

В исключительных случаях ngOnInit может быть полностью заглушен, чтобы обеспечить изоляцию для других компонентов (например, некоторая логика шаблона).

наследование

Дочерние классы могут только расширять конструкторы, но не заменять их.

Так как thisне может быть передано ранееsuper() , это накладывает ограничения на приоритет инициализации.

Учитывая, что компонент или директива Angular использует ngOnInitлогику инициализации, не зависящую от времени, дочерние классы могут выбирать, super.ngOnInit()вызывать ли и когда:

ngOnInit() {
  this.someMethod();
  super.ngOnInit();
}

Это было бы невозможно реализовать с помощью одного конструктора.

Настой Эстус
источник
12

Приведенные выше ответы на самом деле не отвечают на этот аспект исходного вопроса: что такое хук жизненного цикла? Мне потребовалось некоторое время, чтобы понять, что это значит, пока я не подумала об этом таким образом.

1) Скажите, что ваш компонент - человек. У людей есть жизни, которые включают в себя много стадий жизни, и тогда мы истекаем.

2) Наш человеческий компонент может иметь следующий сценарий жизненного цикла: «Родился», «Ребенок», «Начальная школа», «Молодой взрослый», «Взрослый среднего возраста», «Старший взрослый», «Умерший», «Утилизированный».

3) Скажем, вы хотите иметь функцию для создания детей. Чтобы это не усложнялось и не было достаточно юмористическим, вы хотите, чтобы ваша функция вызывалась только на стадии «Молодого взрослого» в жизни человеческого компонента. Таким образом, вы разрабатываете компонент, который активен только тогда, когда родительский компонент находится на стадии «Молодой взрослый». Крючки помогают вам сделать это, сигнализируя об этом этапе жизни и позволяя вашему компоненту воздействовать на него.

Прикольные вещи. Если вы позволите своему воображению приступить к написанию чего-то подобного, это будет сложно и забавно.

Престон
источник
7

Конструктор представляет собой метод в JavaScript и рассматривается как признак класса в ES6 .При класс конкретизируется сразу не запускается конструктор ли он используется в угловых рамках или not.So его называют двигателем JavaScript и Угловая не имеет контроль над этим.

import {Component} from '@angular/core';
@Component({})
class CONSTRUCTORTEST {

//This is called by Javascript not the Angular.
     constructor(){
        console.log("view constructor initialised");
     }
}

Класс "ConstructorTest" описан ниже, поэтому он внутренне вызывает конструктор (все это происходит с помощью JavaScript (es6) без Angular).

new CONSTRUCTORTEST();

Вот почему в Angular отображается обработчик жизненного цикла ngOnInit, когда Angular завершает инициализацию компонента.

import {Component} from '@angular/core';
@Component({})
class NGONINITTEST implements onInit{
   constructor(){}
   //ngOnInit calls by Angular
   ngOnInit(){
     console.log("Testing ngOnInit");
   }
}

Сначала мы создаем экземпляр класса, как показано ниже, что происходит с непосредственными запусками метода конструктора.

let instance = new NGONINITTEST();

ngOnInit вызывается Angular при необходимости, как показано ниже:

instance.ngOnInit();

Но вы можете спросить, почему мы используем конструктор в Angular?

Ответ заключается в внедрении зависимостей . Как уже упоминалось ранее, конструктор вызывает движок JavaScript сразу же, когда создается экземпляр класса (перед вызовом ngOnInit в Angular), поэтому машинописный текст помогает нам получить тип зависимостей, определенных в конструкторе, и, наконец, сообщает Angular, какой тип зависимостей мы хотим использовать в этом конкретном компоненте.

Негин
источник
7

Здесь нужно соблюдать две вещи:

  1. Конструктор вызывается всякий раз, когда создается объект этого класса.
  2. ngOnInit вызывается после создания компонента.

Оба имеют разное удобство использования.

UniCoder
источник
5

Конструктор () является методом по умолчанию в жизненном цикле компонента и используется для внедрения зависимости. Конструктор - это функция Typescript.

ngOnInit () вызывается после конструктора, а ngOnInit вызывается после первого ngOnChanges.

то есть:

Constructor () -->ngOnChanges () -->ngOnInit ()

как упомянуто выше, ngOnChanges()вызывается, когда изменяется значение привязки ввода или вывода.

Шаджин Чандран
источник
4

Оба метода имеют разные цели / обязанности. Задача конструктора (который поддерживается языком) состоит в том, чтобы убедиться, что инвариант представления выполняется. В противном случае указывается, чтобы убедиться, что экземпляр действителен, давая правильные значения членам. Разработчик должен решить, что означает «правильный».

Задача метода onInit () (который является угловым понятием) состоит в том, чтобы разрешить вызовы метода для правильного объекта (инвариант представления). Каждый метод должен, в свою очередь, убедиться, что инвариант представления выполняется, когда метод завершается.

Конструктор должен использоваться для создания «правильных» объектов, метод onInit дает вам возможность вызывать вызовы метода в четко определенном экземпляре.

Бруно Раншарт
источник
4

Конструктор. Метод конструктора в классе ES6 (или в данном случае в TypeScript) - это функция самого класса, а не функция Angular. Он не контролируется Angular, когда вызывается конструктор, что означает, что он не подходит, чтобы сообщать, когда Angular завершил инициализацию компонента. Движок JavaScript вызывает конструктор, а не Angular напрямую. Вот почему был создан хук жизненного цикла ngOnInit (и $ onInit в AngularJS). Учитывая это, есть подходящий сценарий для использования конструктора. Это когда мы хотим использовать внедрение зависимостей - в основном для «связывания» зависимостей в компоненте.

Поскольку конструктор инициализируется движком JavaScript, а TypeScript позволяет нам сообщать Angular, какие зависимости нам необходимы для сопоставления с определенным свойством.

ngOnInit предназначен для того, чтобы дать нам сигнал о том, что Angular завершил инициализацию компонента.

Этот этап включает в себя первый проход в Обнаружении изменений свойств, которые мы можем привязать к самому компоненту, например, используя декоратор @Input ().

В связи с этим свойства @Input () доступны внутри ngOnInit, но не определены внутри конструктора

Вишал Гулати
источник
2

Конструктор - первый, и это иногда случается, когда данные @input равны нулю! поэтому мы используем Constructor для объявления сервисов, а ngOnInit происходит после. Пример для Contrutor:

 constructor(translate: TranslateService, private oauthService: OAuthService) {
    translate.setDefaultLang('En');
        translate.use('En');}

Пример для onInit:

ngOnInit() {
    this.items = [
      { label: 'A', icon: 'fa fa-home', routerLink: ['/'] },
      { label: 'B', icon: 'fa fa-home', routerLink: ['/'] }]
}

Я думаю, что onInit похож на InitialComponents () в winForm.

user1012506
источник
1

В угловых жизненных циклах

1) Угловой инжектор определяет параметр конструктора (ов) и создает экземпляр класса.

2) Следующий угловой цикл жизненного цикла

Угловые крючки жизненного цикла

ngOnChanges -> вызвать привязку параметров директивы.

ngOnInit -> Начать угловой рендеринг ...

Вызвать другой метод с состоянием углового жизненного цикла.

Мусульманин Шахсаван
источник
1

constructorВызывается , когда угловые «instanciates / конструкции» компонент. ngOnInitМетод представляет собой крючок , который представляет собой часть инициализации компоненты жизненного цикла. Хорошей практикой является использование его только для сервисного внедрения :

constructor(private 
    service1: Service1,
    service2: Service2
){};

Даже если это возможно, вы не должны делать какую-то «работу» внутри. Если вы хотите запустить какое-то действие, которое должно произойти при «инициализации» компонента, используйте ngOnInit:

ngOnInit(){
    service1.someWork();
};

Более того, действия, которые включают входные свойства , исходящие от родительского компонента, не могут быть выполнены в конструкторе. Они должны быть размещены в ngOnInitметоде или другом крючке. То же самое относится к элементу, связанному с представлением (DOM), например, к элементам viewchild :

@Input itemFromParent: string;
@ViewChild('childView') childView;

constructor(){
    console.log(itemFromParent); // KO
    // childView is undefined here
};

ngOnInit(){
    console.log(itemFromParent); // OK
    // childView is undefined here, you can manipulate here
};
veben
источник
0

constructor() используется для внедрения зависимости.

ngOnInit(), ngOnChanges()И ngOnDestroy()т.д. методы жизненного цикла. ngOnChanges()будет вызван первым, до того ngOnInit(), как значение связанного свойства изменится, оно НЕ будет вызвано, если не было изменений. ngOnDestroy()вызывается при удалении компонента. Чтобы использовать это, OnDestroyдолжен быть implementотредактирован классом.

xameeramir
источник
1
согласен, это коротко и понятно. Например, constructor () предназначен для добавления сервисных объектов, ngOnInit () предназначен для манипулирования компонентами с необходимыми вызовами сервисных функций.
Стив
0

Я нашел ответ и попытался перевести его на английский: этот вопрос все еще возникал, даже в технических интервью. На самом деле, между ними есть большое сходство, но есть и некоторые различия.

  • Конструктор является частью ECMAScript. С другой стороны, ngOnInit () - это понятие угловое.

  • Мы можем вызывать конструкторы во всех классах, даже если мы не используем Angular

  • LifeCycle: конструктор вызывается перед ngOnInt ()

  • В конструкторе нельзя назвать элементы HTML. Однако в ngOnInit () мы можем.

  • Как правило, вызовы служб в ngOnInit (), а не в конструкторе

    Источник: http://www.angular-tuto.com/Angular/Component#Diff

Дуду
источник
0

Конструктор

Функция конструктора поставляется с каждым классом, конструкторы не являются специфичными для Angular, но представляют собой концепции, полученные из объектно-ориентированных проектов. Конструктор создает экземпляр класса компонента.

OnInit

ngOnInitФункция является одним из методов жизненного цикла угловую компонента. Методы жизненного цикла (или хуки) в компонентах Angular позволяют запускать фрагмент кода на разных этапах жизни компонента. В отличие от метода конструктора, ngOnInitметод происходит из интерфейса Angular ( OnInit), который компонент должен реализовать для использования этого метода. ngOnInitВызывается метод вскоре после того , как компонент создан.

декабрь
источник
0

Конструктор выполняется, когда создается экземпляр класса. Это не имеет ничего общего с угловым. Это особенность Javascript, и Angular не контролирует ее

NgOnInit является специфичным для Angular и вызывается, когда Angular инициализирует компонент со всеми его входными свойствами.

Свойства @Input доступны в хуке жизненного цикла ngOnInit. Это поможет вам выполнить некоторые действия по инициализации, такие как получение данных с внутреннего сервера и т. Д. Для отображения в представлении.

Свойства @Input отображаются как неопределенные внутри конструктора

dasunse
источник
-1

Конструктор - это функция, выполняемая при сборке компонента (или другого класса).

ngOnInit - это функция, принадлежащая к группам методов жизненного цикла компонента, и они выполняются в другой момент нашего компонента (именно поэтому и называются жизненным циклом). Вот список всех из них:

введите описание изображения здесь Конструктор будет выполнен перед любой функцией жизненного цикла.

Przemek Struciński
источник