2016-08-11 5 views
0

Когда мой шаблон отображает функцию внутри ngOnChanges, срабатывает один раз, а затем только при изменении @input. Является ли это ожидаемым поведением и как я могу его предотвратить?Angular 2: ngOnChanges срабатывает, когда шаблон визуализирует

Ребенок:

export class MobileMenuComponent implements OnInit, OnChanges { 

@Input('test') dezeTest: string; 

//declare menu 
menu; 

constructor() { 

    //define menu 

    this.menu = {state: 'inactive'}; 

} 

togglemenu() { 

    var that = this; 

    if (that.menu.state === 'inactive'){ 

     that.menu.state = 'active'; 

    } 

    else { 

     that.menu.state = 'inactive'; 

    } 

} 

ngOnChanges(changes: SimpleChanges) { 


    this.togglemenu(); 


} 
} 

ответ

1

Это нормальное поведение ngOnChanges.

Метод ngOnChanges будет срабатывать в первый раз, потому что ваши свойства были проверены и затем запускаются при обновлении свойства. Из documentation, вы можете увидеть

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

Если вы хотите изменить его, вам необходимо подумать о том, как его изменить. Это не очень понятно из вашего вопроса, но если вы хотите, чтобы ngOnChanges снова запускались, когда свойство обновляется (я думаю, что вы хотите этого из-за вашего toggleMenu(), вы можете подумать об использовании ngOnInit() вместо ngOnChanges(). может блокировать togglemenu();... после того, как в первый раз

firstrun : boolean = true; // class variable 
ngOnChanges(changes : SimpleChanges){ 
    if(firstrun){ 
     this.togglemenu(); 
     firstrun = false; 
    } 
    } 

Альтернативно, как намекают ранее другой lifecycle hook могли бы удовлетворить ваши потребности лучше

+0

Спасибо, вторая вещь, которую я искал. История этого вопроса заключается в том, что пользователь должен нажать кнопку в одном компоненте, и что-то должно произойти в дочернем компоненте. Есть ли лучший способ сделать это без ngOnChanges? – Dirk

+0

@Dirk Вы также можете использовать реактивные расширения для этого. Вы можете создать объект где-нибудь, в котором содержится состояние меню (объект логического, истинного/ложного). Когда кнопка нажата на компоненте - измените состояние объекта. Это создаст событие, которое может наблюдать абонент.(У ваших детей вы можете наблюдать это событие и соответствующим образом обрабатывать изменение) –

+0

Хорошо. Так любопытно, как HTTP-запрос с наблюдаемым. У вас есть что-то, что я могу посмотреть или прочитать, чтобы узнать больше об этом? Потому что это похоже на то, что наблюдаемые являются более чистым решением. – Dirk

1

Как предложил Дилан Meeus, его нормальное поведение но я бы предложил другое решение, которое использует преимущества прошедшего SimpleChang e объект. он содержит previousValue и currentValue .. изначально предыдущее значение не задано. https://angular.io/docs/ts/latest/api/core/index/SimpleChange-class.html

ngOnChanges(changes : any){ 
    if(changes.menu.previousValue){ 
     this.togglemenu(); 
    } 
} 

дополнительно заботиться о OnChanges, так как он срабатывает на каждом входе парам ... (можно добавить еще немного в будущем)

+0

Также хорошее решение. Но у меня проблемы. Когда я пытаюсь получить ключи от изменений, которые var Bookscript дает мне, не выходит из ошибки. «Свойство« menubutton »не существует в типе« SimpleChanges ». любой« Если я вношу изменения в консоль, я вижу, что у нее есть свойство menubutton. Что я делаю неправильно? Редактирование: кажется, что коды работают. Все еще хотелось бы отказаться от ошибки TS. – Dirk

+0

Хорошо, я вижу, вы можете либо создать собственное определение SimpleChanges, либо определить его как любое. ngOnChanges (изменения: any) –

+0

Сделал последний и, похоже, сработает. Благодарю. – Dirk

1

Для расширения существующих ответов, а также обратиться к типизации вопрос, поднятый в комментарии в то же время:

Поле SimpleChange # firstChange существует для этого точного случая.

В качестве альтернативы, так как значение установлено на вашем компоненте перед ngOnChanges называется, вы также можете проверить, если поле изменилось, а затем, если он установлен:

ngOnChanges(changes: { myField: SimpleChange }) { 
    if(changes.myField && this.myField){ 
     // do a thing only when 'myField' changes and is not nullish. 
    } 
    // Or, if you prefer: 
    if(changes.myField && changes.myField.firstChange){ 
     // Do a thing only on the first change of 'myField'. 
     // WARNING! If you initialize the value within this class 
     // (e.g. in the constructor) you can get null values for your first change 
    } 
} 

Еще одно маленькое предупреждение: Если бы вы были используйте инструменты, такие как WebStorm, чтобы переименовать «myField» на ваш компонент, «myField» параметров метода ngOnChanges ({myField: SimpleChange}) НЕ будет обновляться. Это может привести к некоторым ошибкам инициализации компонентов.

Смежные вопросы