Чи повинна директива angularjs безпосередньо взаємодіяти із службами чи це вважається антидіаграмою?


35

Який вважається кращим:

  • наявність директиви, яка безпосередньо взаємодіє з послугами

або

  • мати директиву, яка розкриває певні гачки, до яких контролер може пов'язувати поведінку (за допомогою служб)?

Мені потрібно трохи більше контексту того, що ви хочете досягти, що повідомляється, скільки вихідного коду слід очікувати, який ваш домен, як він має масштабувати?
Користувач

Це директива, відповідальна за надання віджета для коментування - у ньому відображається поле для коментарів, а також кнопки надсилання / скасування. Ця директива передбачається використовувати лише в одному контексті - коментуючи "документ". Те, як в даний час обробляється контролер, виявляє функції для створення фактичного коментаря (контролер отримує введений екземпляр служби коментарів). Інший спосіб зробити це - інкапсуляція всієї справи (разом із помилками / успіхом) в директиві (директива отримає введення служби коментарів).
WTK

Відповіді:


24

Директива найкраща (як правило), коли вона коротка (з кодом), (потенційно) повторно використана і має обмежений спектр функціональних можливостей. Створюючи директиву, яка включає інтерфейс користувача і залежить від послуги (що я припускаю, що обробляє з'єднання з бекендом), не тільки надає їй 2 функціональних ролі, а саме:

  • Керування інтерфейсом користувача для відображення / введення даних віджета.
  • Подання в бекенд (через сервіс).

але також робить його менш повторним у використанні, оскільки потім ви не можете використовувати його знову з іншою службою або з іншим інтерфейсом (принаймні, не просто).

Приймаючи ці рішення, я часто порівнюю з вбудованими елементами HTML: наприклад <input>, <textarea>або <form>: вони повністю незалежні від будь-якого конкретного бекенда. HTML5 надав <input>елементу кілька додаткових типів, наприклад date, який все ще не залежить від бекенда, і куди саме надходять дані або як вони використовуються. Вони є суто інтерфейсними елементами. Ваші користувацькі віджети, побудовані за допомогою директив, я думаю, повинні йти за тією ж схемою, якщо це можливо.

Однак це ще не кінець історії. Виходячи за межі аналогії із вбудованими елементами HTML, ви можете створювати повторно використовувані директиви, які обидва викликають служби, та використовувати суто директиву інтерфейсу користувача, як і це може використовувати <textarea>. Скажіть, що ви хочете використовувати якийсь HTML таким чином:

<document document-url="'documents/3345.html'">
 <document-data></document-data>
 <comments></comments>
 <comment-entry></comment-entry>
</document>

Для кодування commentEntryдирективи ви можете зробити дуже невелику директиву, яка містить просто контролер, який пов'язує службу з інтерфейсом інтерфейсу користувача. Щось на зразок:

app.directive('commentEntry', function (myService) {
  return {
    restrict: 'E',
    template: '<comment-widget on-save="save(data)" on-cancel="cancel()"></comment-widget>',
    require: '^document',
    link: function (scope, iElement, iAttrs, documentController) {
      // Allow the controller here to access the document controller
      scope.documentController = documentController;
    },
    controller: function ($scope) {
      $scope.save = function (data) {
        // Assuming the document controller exposes a function "getUrl"
        var url = $scope.documentController.getUrl(); 

        myService.saveComments(url, data).then(function (result) {
          // Do something
        });
      };
    }
  };
});

Доводячи це до крайності, можливо, вам ніколи не потрібно мати ручний ng-controllerатрибут у HTML: ви можете це робити за допомогою директив, якщо кожен безпосередньо має чітку роль "UI" або чітку роль "data".

Я повинен зазначити мінус: він надає більше «рухомих частин» додатку, що додає трохи складності. Однак, якщо кожна частина має чітку роль, і вона добре (перевірена одиниця + E2E), я можу стверджувати, що це вартує і загальної вигоди в довгостроковій перспективі.


59

Дозвольте мені не погодитися з відповіддю Міхала Шаремзи.

Хоча його відповідь теоретично правильна, вона не дуже практична для реального світу.

Я говорю, що тому я думав так і намагався застосувати це у великому реальному додатку, який будують я та моя команда, і це стало занадто клопітно.

Аналогія з мовою HTML не є хорошою, тому що ви не повинні прагнути створювати загальні цілі, надзвичайно багаторазові директиви, оскільки ви не будуєте загальну програму, як веб-браузер.

Натомість слід скористатися директивами для побудови конкретної мови домену (DSL) для вашої програми, яка живе у власному домені.

Це не означає, що всі директиви не повинні бути загальними. Деякі можуть бути, якщо це в їх природі. Якщо ви створюєте спеціальний інструмент вибору дат, будь-ласка, зробіть його загальним і багаторазовим для використання в додатках.

Але якщо ви будуєте щось на зразок вікна для входу, який прив'язується до вашого бек-енду, просто зробіть це.

Єдиним головним правилом має бути: ніколи не дублюйте код (абстрагуйте невеликі шматочки до фабрик і служб) і не робіть його перевіряючим через введення залежності. На щастя, з Angular, це шматок пирога.

Не ускладнювати. :)


5
Гарні моменти Дема - хоча я прийняв відповідь Міхала, я згоден з вашим підходом, що ми не повинні стрибати обручі, щоб зробити щось для багаторазового використання тільки заради цього. Це був мій первісний інстинкт - пов'язувати службу директивою, тому що це мало сенс, а не тому, як це чи не хотів би зробити гуру angularjs. Врешті-решт я створив директиву з сервісом, який вводиться безпосередньо в неї, і як публічний API я надаю гачок для зворотного дзвінка, який запускається після того, як фактично створені коментарі.
WTK

2

Я думаю, що питання "якщо директива взаємодіє зі службою" залежить від того, що робить ваша служба.

У мене були директиви, які взаємодіють із службами, які нічого не роблять із HTTP-запитами, і я думаю, що це вдалий зразок. Послуги / Фабрики чудово підходять для інкапсуляції більшої логіки, орієнтованої на дані, а директиви відмінно підходять для інкапсуляції логіки, орієнтованої на презентацію. Зазначена мета послуг у кутових документах: "Ви можете використовувати сервіси для організації та обміну кодом у вашому додатку." Це досить широко, але послуги можуть бути використані для досягнення цієї мети в директивах.

Зважаючи на це, я розумію бажання в деяких випадках зробити так, щоб директиви прямо не робили жодних HTTP-запитів. Знову ж таки, це залежить від сервісу та того, як ви організовуєте свої послуги.


1

Відповідно до рамок AngularJS, ми повинні однофабрикати / служби для отримання будь-яких даних із сервера. Так що ці фабрики можна повторно використовувати через додаток, не переписуючи те саме. Внутрішньою директивою ми можемо викликати ці фабрики, щоб отримати дані, отримані з Api / сервера.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.