2016-06-04 2 views
2

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

  1. На основе пользовательского события, родительский компонент обновляет компонент собственности ребенка
  2. Этого обновления пожары события в компоненте ребенка, который обновляет свойство на материнской
  3. Родителем обновления свойства запускает другое событие, обновляет дочерний компонент
  4. ...

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

Как разрешается с угловым 2? В какой момент в приведенном выше примере фактически происходит обнаружение изменений?

ответ

4

Я прочитал, что Угловое обнаружение 2 изменения ... становится стабильным после одного прохода

Угловые 2 не «получить стабильные». С приложениями Angular 2 мы отвечаем за то, что мы пишем наше приложение таким образом, чтобы оно всегда было стабильным после одного прохода.

По умолчанию (например, вы не используете стратегию обнаружения OnPush изменений на каких-либо компоненты, не так ли detach() какие-либо компоненты), обнаружение изменений работает следующим образом:

  • Zone.js обезьяньей заплатой асинхронного события – например, событие (click), ответ XHR, таймер setTimeout(). Выполняется обратный вызов, связанный с этим событием, который может изменить любой вид или данные приложения в нашем приложении. Затем, из-за обезьяны-патча, происходит обнаружение углового изменения. Другими словами, по умолчанию (например, вы не являетесь manually triggering change detection), только обнаружение изменений асинхронных событий, связанных с обезьяной, вызывает обнаружение изменений.
  • Начиная с корневого компонента и прохода вниз по дереву компонентов (обход по глубине), каждая привязка данных проверяется на изменение. Если обнаружено изменение, это изменение «распространяется».В зависимости от типа связывания с шаблоном распространение может
    • распространять измененное значение в DOM. Например, когда используется привязка {{}}, новое значение распространяется на свойство textContent соответствующего элемента DOM.
    • распространять измененное значение на дочерний компонент. Например, при использовании привязки входных свойств ([childInputProperty]="parentProperty") новое значение распространяется на свойство дочернего ввода.
  • Если вы находитесь в режиме разработчика, все компоненты загрязнены проверены еще раз, но нет распространения не происходит. Эта вторая грязная проверка помогает нам найти проблемы с нашим кодом, например, если мы нарушили idempotent rule, что является причудливым способом сказать, что одно из наших привязок (его выражение в шаблоне) имеет побочные эффекты. Другими словами, дополнительные проверки режима Dev сообщают нам, если наш код нестабилен после одного прохода.

Побочные эффекты не допускаются в Угловом 2. В связи с вашим вопросом дочерний компонент поэтому не должен изменять родительское свойство в результате распространения свойства ввода. Итак, вы могли бы сказать, что Angular 2 «разрешает» ситуацию, о которой вы просили, не разрешая ее.

Это не так плохо, как может показаться. Единственный способ, которым я знаю, что распространение входного свойства может изменить родительское свойство, - это если дочерний компонент реализует метод setter для свойства ввода, который модифицирует другое свойство, которое родительский отображает в своем шаблоне. (Вот old plunker, который делает это - см. Метод @Input set backdoor().) Обычно вы не сделали бы этого. Если вам нужно это сделать, тогда комментарий Гюнтера будет выглядеть следующим образом: сделайте изменение внутри setTimeout(), поэтому оно станет частью следующего цикла обнаружения изменений.

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

Так что если вы вносите изменения в обработчики событий, никаких проблем. Существует только проблема, если ваш сеттер делает что-то странное.

+1

Спасибо за подробное объяснение. Это помогло мне лучше понять механизм обнаружения изменений. Приветствия. – Fjut

+2

Вы можете просто использовать 'setTimeout (changeParentHere)', если это действительно то, что вы хотите. –

2

В обнаружении изменения devMode выполняет два последовательных оборота. Если 2-й поворот распознает изменения, он бросает. Поэтому само определение изменения не должно вызывать изменения модели.

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

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

Этот способ обнаружения углов2 позволяет избежать циклов.

+0

Спасибо за ответ. Я принял ответ Марка, поскольку он дает более подробное объяснение. – Fjut

+0

Несомненно, он - CD-плеер :) –

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