Компонент Angular 1.5 против старой директивы — где функция ссылки?

Я читал эту замечательную недавнюю статью о новом .component() helper в Angular 1.5, который должен помочь всем в конечном итоге перейти на Angular 2. Все выглядит красиво и просто, но я не смог найти никакой информации о манипулировании DOM внутри компонентов.

Однако есть свойство template, которое может быть функцией и принимать аргументы $element и $attrs. Тем не менее мне не ясно, является ли это заменой функции link. Это не так.


person troorl    schedule 14.11.2015    source источник


Ответы (6)


EDIT 2/2/16: Документация 1.5 теперь охватывает компоненты: https://docs.angularjs.org/guide/component


Некоторые мысли, основанные на некоторых чтениях (ссылки ниже):

  • Компоненты не заменяют директивы. Компонент — это особый тип директивы, которая организует контроллер с помощью шаблона.

  • Компоненты не имеют функции связи, а контроллеры по-прежнему не используются для манипуляций с DOM.

  • Если вам нужны манипуляции с DOM, ваш компонент может использовать другие директивы, которые включают эту манипуляцию с DOM в функцию ссылки.

Мне потребовалось некоторое время, чтобы понять это, но как только я это понял, это обрело смысл: компоненты — это директивы, но не все директивы являются — или должны быть — компонентами.

Вопрос о функциях ссылок является естественным, или был для меня естественным, когда я думал, что компоненты заменяют директивы. Почему? Потому что нас учили помещать манипуляции с DOM в функцию ссылки директивы: «Директивы, которые хотят изменить DOM, обычно используют параметр ссылки для регистрации прослушивателей DOM, а также для обновления DOM». https://docs.angularjs.org/guide/directive.

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

Фоновое чтение

То, что я сказал выше, на самом деле является перефразированием того, что сказал Тодд Мотто в, возможно, лучшем (пока что) обсуждении компонентов и директив:

https://www.reddit.com/r/angularjs/comments/3taxjq/angular_15_is_set_to_introduce_the_component/

Было бы полезно включить эти комментарии в более общую статью.

В большинстве статей о компонентах функция ссылки не упоминается (это не значит, что это плохие статьи):

https://toddmotto.com/exploring-the-angular-1-5-component-method/

https://medium.com/@tomastrajan/component-paradigm-cf32e94ba78b#.vrbo1xso0

https://www.airpair.com/angularjs/posts/component-based-angularjs-directives

Или, когда упоминается функция ссылки, она заключена в круглые скобки:

http://teropa.info/blog/2015/10/18/refactoring-angular-apps-to-components.html

В одной статье говорится эти компоненты «используют контроллеры вместо функций связи». Но это не ситуация «вместо»: контроллеры не заменяют функции связи.

person jody tate    schedule 24.01.2016
comment
Хорошо сказано. Я использую компоненты для страниц с дочерними директивами, где необходимы манипуляции с DOM. Сначала это было странно, но работает очень хорошо, особенно с 1.5 multi transclude. - person Phix; 03.02.2016
comment
Я не уверен, почему вы говорите, что не должны выполнять какие-либо манипуляции с dom в компонентах, когда в документации angular прямо сказано: $postLink() - вызывается после того, как этот элемент контроллера и его дочерние элементы были связаны. Подобно функции post-link, этот хук можно использовать для настройки обработчиков событий DOM и прямых манипуляций с DOM. Можешь объяснить, почему тебя это не привлекает? - person pasquers; 08.09.2016
comment
Я не использую в ответе слова «не должен» или «любой» — извините, если это подразумевается. Что касается $postLink, это полезно прочитать: toddmotto.com/angular-1-5-lifecycle-hooks#what-postlink-is-not. - person jody tate; 09.09.2016
comment
Я что-то упускаю или это основной консенсус в отношении того, что компоненты просто разбавлены директивами? Компонент можно было воссоздать как директиву, но директиву не всегда можно было воссоздать как компонент. Компоненты просто не так эффективны, как директивы, потому что им не хватает возможности выполнять манипуляции с DOM. - person jtate; 29.03.2017
comment
это отличный ответ. component.$postLink следует использовать для установки логики после установки DOM. directive.link по-прежнему подходит для манипуляций с DOM. Вы знаете, что пришло время создать директиву, когда вы внедряете $element в свой контроллер компонентов. - person user2954463; 09.08.2017

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

Преимущества компонентов:

более простая конфигурация, чем простые директивы, способствует разумным значениям по умолчанию и лучшим практикам, оптимизированным для архитектуры на основе компонентов. Написание директив для компонентов упростит переход на Angular 2.

Когда нельзя использовать Компоненты:

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

person surekha shelake    schedule 12.04.2016

Обновление (от 22 августа 2017 г.): $inject рекомендуется для этого в AngularJS. Прочтите руководство по стилю: руководство по стилю ссылка и документы AngularJS: документы AngularJS

Для использования привязок DOM в компонентах вместо создания директивы с функцией ссылки вы можете внедрить '$ element' или другую службу, которая вам нужна, в функцию вашего контроллера, например.

app.component('pickerField', {
    controller: PickerField,
    template: '<span>Your template goes here</span>'
  });

  PickerField.$inject = ['$element'];

  function PickerField(element) {
    var self = this;
    self.model = self.node.model;
    self.open = function() {
      console.log('smth happens here');
    };
    element.bind('click', function(e) {
      console.log('clicked from component', e);
      self.open();
    });
  }

person Ekaterina Tokareva    schedule 27.12.2016
comment
Внедрение $element — плохая практика. Это затрудняет тестирование $componentController. - person user2954463; 09.08.2017
comment
@jdrury На самом деле, это рекомендуемый способ angularJS для внедрения зависимостей. Вы можете прочитать документы: docs.angularjs.org/guide/di#- inject-property-annotation и руководство по стилю github.com/johnpapa/angular-styleguide/blob/master/a1/ Также я обновлю свой ответ этими ссылками - person Ekaterina Tokareva; 22.08.2017
comment
Я согласен - если вам нужно получить доступ к $element в компонент, ваш путь правильный. Но мой аргумент заключается в том, что если вам нужно получить доступ к $element, вы должны использовать директиву вместо компонента. Моя причина такова: если вы внедрите $element в компонент, вам придется создать поддельный $element через $compile при модульном тестировании с помощью $componentController. - person user2954463; 22.08.2017

Итак, похоже, что сейчас контроллер — подходящее место для него, поскольку он единственно возможный. Также мы не можем использовать параметр replace в помощнике компонента.

person troorl    schedule 14.11.2015
comment
replace устарел. - person svarog; 19.07.2016

Вы можете использовать функцию $postLink(), которая находится в новейшем angular.

https://docs.angularjs.org/guide/component

Подобно функции post-link, этот хук можно использовать для настройки обработчиков событий DOM и прямых манипуляций с DOM.

person Szymon    schedule 28.01.2019

Согласно текущей документации Angular2 (см. https://github.com/angular/angular/blob/master/modules/angular2/docs/core/02_directives.md) в Angular2 по-прежнему будут директивы. Таким образом, вы сможете использовать как @Directive, так и @Component, где:

  • Директивы полезны для инкапсуляции поведения.
  • Компонент — это директива, которая использует теневую модель DOM для создания инкапсулированного визуального поведения. Компоненты обычно используются для создания виджетов пользовательского интерфейса или для разбиения приложения на более мелкие компоненты.

Итак, в соответствии с этим, если вам нужны манипуляции с DOM, вам нужно будет использовать @Directive, поэтому Angular.directive в Angular 1.x. Привязки событий можно выполнить с помощью свойств host. Что касается манипулирования DOM как такового, по-прежнему отсутствует документация (например, https://github.com/angular/angular/blob/master/modules/angular2/docs/core/09_compilation.md или https://github.com/angular/angular/blob/master/modules/angular2/docs/core/08_lifecycle.md), но вы можете искать Lifecycle, как предлагается здесь https://stackoverflow.com/a/32062065.

В качестве короткого ответа: с Angular 1.5+ продолжайте использовать angular.directive, если у вас есть доступ к DOM, в противном случае инкапсулируйте в angular.component. Также постарайтесь максимально сократить использование $scope для событий, не связанных с домом, и предпочитайте для этого RxJS, см. https://medium.com/front-end-developers/managing-state-in-angular-2-using-rxjs-b849d6bbd5a5#.obgb6dl6n ,

person barraq    schedule 27.01.2016