Spec-Zone.ru › Angular.js 1.7

Улучшить эту документациюДекораторы в AngularJS

ПРИМЕЧАНИЕ: Это руководство предназначено для разработчиков, уже знакомых с основами AngularJS. Если вы только начинаете, мы рекомендуем сначала ознакомиться с руководством по началу работы.

Что такое декораторы?

Декораторы — это паттерн проектирования, используемый для разделения модификации или декорирования класса без изменения исходного кода. В AngularJS декораторы — это функции, которые позволяют изменять сервис, директиву или фильтр перед их использованием.

Как использовать декораторы

Существует два способа регистрации декораторов

  • $provide.decorator, и
  • module.decorator

Каждый предоставляет доступ к $delegate, который представляет собой экземпляр сервиса/директивы/фильтра, перед тем, как его передать сервису, который его потребовал.

$provide.decorator

Функция декоратора позволяет получить доступ к $delegate сервиса после его создания. Например:

angular.module('myApp', [])

.config([ '$provide', function($provide) {

  $provide.decorator('$log', [
    '$delegate',
    function $logDecorator($delegate) {

      var originalWarn = $delegate.warn;
      $delegate.warn = function decoratedWarn(msg) {
        msg = 'Decorated Warn: ' + msg;
        originalWarn.apply($delegate, arguments);
      };

      return $delegate;
    }
  ]);
}]);

После создания сервиса $log декоратор срабатывает. Функция декоратора получает объект $delegate, чтобы предоставить доступ к сервису, который соответствует селектору в декораторе. Этот $delegate будет сервисом, который вы декорируете. Возвращаемое значение функции предоставленной декоратору заменит декорируемый сервис, директиву или фильтр.

Этот $delegate может быть изменён или полностью заменён. Учитывая сервис myService с методом someFn, следующие решения могут быть жизнеспособными:

Полная замена $delegate

angular.module('myApp', [])

.config([ '$provide', function($provide) {

  $provide.decorator('myService', [
    '$delegate',
    function myServiceDecorator($delegate) {

      var myDecoratedService = {
        // new service object to replace myService
      };
      return myDecoratedService;
    }
  ]);
}]);

Изменение $delegate

angular.module('myApp', [])

.config([ '$provide', function($provide) {

  $provide.decorator('myService', [
    '$delegate',
    function myServiceDecorator($delegate) {

      var someFn = $delegate.someFn;

      function aNewFn() {
        // new service function
        someFn.apply($delegate, arguments);
      }

      $delegate.someFn = aNewFn;
      return $delegate;
    }
  ]);
}]);

Расширение $delegate

angular.module('myApp', [])

.config([ '$provide', function($provide) {

  $provide.decorator('myService', [
    '$delegate',
    function myServiceDecorator($delegate) {

      function helperFn() {
        // an additional fn to add to the service
      }

      $delegate.aHelpfulAddition = helperFn;
      return $delegate;
    }
  ]);
}]);
Обратите внимание, что возвращаемое значение функции декоратора заменит декорируемый объект. Например, отсутствие оператора return уничтожит весь декорируемый объект.

Декораторы имеют разные правила для различных сервисов. Это связано с тем, что сервисы регистрируются по-разному. Сервисы выбираются по имени, однако фильтры и директивы выбираются путём добавления "Filter" или "Directive" в конец имени. $delegate определяется типом сервиса.

Тип сервиса Селектор $delegate
Сервис serviceName Значение, возвращаемое сервисом object или function
Директива directiveName + 'Directive' Экземпляр Array.<DirectiveObject>1
Фильтр filterName + 'Filter' Значение, возвращаемое фильтром function

1. Может быть зарегистрировано несколько директив с одним и тем же селектором/именем

ПРИМЕЧАНИЕ: Разработчики должны внимательно подходить к тому, как и почему они изменяют $delegate сервиса. Необходимо не только сохранять ожидаемое поведение для потребителей, но и учитывать, что некоторые функции (например, регистрация директив) не происходят после декорации, а во время создания/регистрации исходного сервиса. Это означает, например, что действие, такое как добавление объекта директивы в массив $delegate директив, скорее всего, приведёт к неожиданному поведению. Кроме того, следует проявлять особую осторожность при декорировании основных сервисов, директив или фильтров, так как это может неожиданно или негативно повлиять на функциональность фреймворка.

module.decorator

Эта функция аналогична функции $provide.decorator, но доступна через API модуля. Это позволяет отделить декоративные паттерны от блоков конфигурации модулей.

Как и в случае с $provide.decorator, функция module.decorator выполняется во время фазы конфигурации приложения. Это означает, что вы можете определить module.decorator до определения декорируемого сервиса.

Поскольку вы можете применять несколько декораторов, важно отметить, что применение декораторов всегда происходит в порядке объявления:

  • Если сервис декорируется как $provide.decorator, так и module.decorator, декораторы применяются в указанном порядке:
angular
.module('theApp', [])
.factory('theFactory', theFactoryFn)
.config(function($provide) {
  $provide.decorator('theFactory', provideDecoratorFn); // runs first
})
.decorator('theFactory', moduleDecoratorFn); // runs seconds
  • Если сервис был объявлен несколько раз, декоратор будет декорировать последний объявленный сервис:
angular
  .module('theApp', [])
  .factory('theFactory', theFactoryFn)
  .decorator('theFactory', moduleDecoratorFn)
  .factory('theFactory', theOtherFactoryFn);

// `theOtherFactoryFn` is selected as 'theFactory' provider and it is decorated via `moduleDecoratorFn`.

Примеры применения

В следующих разделах представлены примеры декоратора сервиса, декоратора директивы и декоратора фильтра.

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

Пропущенные интерполированные выражения в атрибутах ng-href могут легко остаться незамеченными. Мы можем декорировать ngHref чтобы предупреждать нас об этих случаях.

Предположим, что мы создали приложение, которое использует стандартный формат для многих наших фильтров Date. Внезапно требования изменились (что случается нечасто), и нам нужно, чтобы все наши стандартные даты были отформатированы как 'shortDate', а не как 'mediumDate'.

© 2010–2018 Google, Inc.
Licensed under the Creative Commons Attribution License 4.0.
https://code.angularjs.org/1.7.8/docs/guide/decorators

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API