Подтвердить что ты не робот

Когда писать директиву?

Angular предоставляет нам механизм для написания директив, который чрезвычайно эффективен в том, что он может сделать. Но я все время задаюсь вопросом - в каком сценарии вы должны на самом деле писать собственную собственную собственную директиву.

Мы продолжаем видеть вопросы внутри и вокруг Qaru с различными людьми, пытающимися написать директивы, которые (на мой взгляд) не обязательно должны быть написаны в первую очередь. В большинстве случаев их можно решить с помощью комбинации повтора, переключения и показа. См. Примеры вопросов, содержащих директивы, которые, я думаю, не должны быть директивами в первую очередь!

https://stackoverflow.com/info/16101073/angularjs-directive-is-not-working-in-ie-10

Нажмите кнопку "Пожарная кнопка" в AngularJS

angularjs: использование директивы внутри ui-bootstrap modal

Некоторые примеры сценариев. Я не собираюсь на них в любом случае... потому что я уверен, что кому-то не понятно, когда мы должны использовать/писать директиву.

Мы видим сценарий, в котором люди используют директивы в качестве механизма для шаблонов. Правильно ли это? Или есть лучший способ? (ng-include, возможно?) Есть ли какие-либо недостатки/недостатки для использования директив в качестве механизма шаблонов? Причина этого вопроса заключается в том, что иногда мне интересно, пишут ли люди директивы, потому что, исходя из мира jquery, первое, что они могут придумать, - это писать DOM, манипулируя кодом, а поскольку способ Angular заключается в том, чтобы не манипулировать DOM в контроллерах, все это тяготеет для написания всего этого кода в директиве.

EDIT:

Я считаю, что эта путаница (из-за того, что вы делаете вещи внутри директивы) возникает потому, что Angular не имеет отдельного понятия "вид" - в отличие от Backbone (у которого есть только "представление", но нет компонента!). Директивы изумительны при определении компонентов. Но я думаю, что если вы используете их для создания "представлений", вы потеряете часть "angular". Это мое мнение, хотя именно поэтому я прошу, что думает остальная часть сообщества Angular.

Хорошая вещь о более простых директивах (директивы, которые делают только 1 вещь!) состоит в том, что они абсолютно просты в тестировании. Если вы посмотрите на все директивы ng, все они делают 1 вещь и делают это очень хорошо.

Каков наилучший способ определения многоразовых "представлений" (а не компонентов!) в Angular? Должно ли это быть написано в директиве? Или есть лучший способ?

Было бы здорово, если бы у одного из Angular Dev было мнение в этом вопросе!

4b9b3361

Ответ 1

Ну... довольно хороший вопрос.

Я считаю, что директивы в основном предназначены для расширения HTML, чтобы вы могли создать DSL", повышая производительность и качество кода.

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

Подводя итог, используя директивы, вы можете:

  • создать поведение DSL для элементов дополнений
  • создать виджеты DSL, чтобы вы могли перестать повторять себя
  • упаковка уже существующих компонентов, покупая производительность.
  • Оптимизация

Дополняющее поведение - не что иное, как компонентное поведение. ng-click, например, добавляет кликабельное поведение к любому элементу. Представьте, что вы создаете приложение с десятками перетаскиваемых элементов. Затем вы создадите директиву по увеличению поведения элементов, заставляя его перетаскивать, даже не касаясь визуального элемента (<span draggable>Test</span>). Еще один пример, представьте, что у вас будут специальные подсказки о наведении мыши. Атрибут title не подходит для этого, тогда вы можете создать свой собственный атрибут my-title, который автоматически создаст ваш "специальный подсказку" при наведении мыши (<span my-title="Some caption">Test</span>).

И когда вы разрабатываете приложение, у вас есть много конкретных понятий и поведения домена. Например, у Stackoverflow есть сильная концепция голосования. Вы можете проголосовать вверх/вниз за вопросы, ответы, комментарии... Таким образом, вы можете создать многоразовую директиву votable, которая добавит "поведение голосования" и "виджет голосования" (стрелки вверх/вниз), чтобы оценить любой элемент.

Это последнее дает нам другое лицо: templating. Не только для ленивых, но и для улучшения качества кода и ремонтопригодности после принципа DRY. Если вы повторяете код контроллеров, структуру HTML или что-то еще, почему бы не создавать шаблоны и не составлять их? Директива - ваш парень для этой работы.

Конечно, у вас также есть общее применение директив. Многие приложения (не говоря о них) полагаются на интерактивные элементы, поэтому мы имеем ng-click, например. Во многих приложениях есть области загрузки. И что бы вы сделали в стиле мышления jQuery? Вы бы создали плагин jQuery. Правильно? В Angular вы создадите Widget Angular (используя директивы). Вы даже можете обернуть уже существующий плагин с помощью директивы и, еще раз, увеличить его поведение, чтобы он мог плавно разговаривать с вашим приложением.

Что касается плагинов плагинов, для каждого плагина jQuery (но может быть MooTools, Ext...), вам нужно создать контроллер, вызвать $('element').plugin() на нем и ухаживать за событиями jQuery изменения и $дайджест вашей области для вас. Это еще одно идеальное использование директивы. Вы можете создать директиву, которая применяет .plugin() к вашему элементу, прислушиваясь к событиям и изменяя/переваривая область действия для вас. Это то, о чем Angular Проект пользовательского интерфейса, посмотрите.

Последний момент - это оптимизация. Недавно я создал приложение и приложение, которое создает таблицы с динамическими столбцами и строками (сеткой). Вопрос в том, что данные обновляются в реальном времени! И ng-repeat внутри ng-repeat, чтобы создавать заголовки, убивал производительность приложения (вложенные циклы в каждом цикле $apply, происходящие каждую половину секунды). Таким образом, вы можете создать директиву, которая создает шаблон столбцов, и по-прежнему использовать ng-repeat внутри него, но вы должны иметь цикл через столбцы только после публикации столбцов.

Итак, завершая работу, я считаю, что директивы касаются компонентов поведения и формы (шаблонов), которые вы покупаете продуктивность и качество кода.

Ответ 2

Я лично пишу директивы довольно много, так как они, как правило, делают мою программу более декларативной.

Пример: в парсере JSON → HTML-формы, который я сделал недавно, я создал директиву "form-element", которая анализирует элемент JSON на создание необходимых директив в качестве его дочерних элементов. Таким образом, у меня есть директива для каждого типа поля, с конкретным поведением и методами. Кроме того, любое общее поведение, разделяемое всеми элементами, находится в директиве form-element.

Таким образом, элемент группы является директивой с шаблоном ng-repeat в нем, а элемент title так же прост, как h1. Но все может иметь одинаковое условное поведение (группа может появляться только в том случае, если предыдущее поле имеет определенное значение, например). И все чрезвычайно чистые - в любое время, когда мне нужно добавлять/изменять, все это отлично подходит, а html является чрезвычайно декларативным.

EDIT - включил фрагмент кода, запрошенный через комментарии.

  /**
  * Form Element
  * ============
  *
  * Handles different elements:
  *   Assigns diferent directives according to the element type
  *   Instanstiates and maintains the active property on the formElem
  */
  .directive("formElement", ['$compile', function($compile){
    return{
        restrict: "E",
        scope:{formElemModel: '='},
        link: function(scope, element, attrs){
            var template = '';
            var type = scope.formElem.type;
            switch (type){
                case "field":
                    template = 
                        "<form-field-"+scope.formElemModel.fieldType+" ng-switch-when='true'>\
                        </form-field-"+scope.formElemModel.fieldType+">";
                    break;
                default:
                    template = "<form-"+type+" ng-switch-when='true' ></form-"+type+">";
                    break;
            }
            element.html(template);
            $compile(element.contents())(scope);

        // Active state of form Element
        scope.formElem.active = true;
        scope.testActive = function(){
          if(scope.$parent.formElem && scope.$parent.formElem.active == false){
            scope.formElem.active = false;
          }
          else{
            scope.formElem.active = 
              scope.meetsRequirements(scope.formElem.requirements);
          }
        }
        scope.$watch("meetsRequirements(formElem.requirements)", scope.testActive);
        scope.$watch("$parent.formElem.active", scope.testActive);
        }
    }
  }])