Spec-Zone.ru › Angular.js 1.8

Улучшить эту документациюДекораторы в 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–2020 Google, Inc.
Licensed under the Creative Commons Attribution License 3.0.
https://code.angularjs.org/1.8.2/docs/guide/decorators

Spec-Zone.ru

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