2015-04-23 3 views
4

Я пытаюсь реализовать пользовательскую директиву для счетчик виджет.Как сделать эту настраиваемую директиву лучше?

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

  • Может ли эта директива быть написана лучше?
  • Как использовать scope: (изолировать область) в лучшем виде?
  • при нажатии любой кнопки сброса Я хочу, чтобы все startnumber были сброшены к «1»?
  • Где наследует scope? Наследует ли он от вызываемого элемента?

HTML фрагмент

<body> 
    <counter-widget startnumber=1 ></counter-widget> 
    <counter-widget startnumber=1 ></counter-widget> 
    <counter-widget startnumber=1 ></counter-widget> 
</body> 

JS сниппет

angular.module("myApp",[]) 
    .directive("counterWidget",function(){ 
    return{ 
    restrict:"E", 
    scope:{ 

    }, 
    link:function(scope,elem,attr){ 
     scope.f = attr.startnumber; 
     scope.add = function(){    
      scope.f = Number(scope.f) + 1; 
     } 
     scope.remove = function(){ 
      scope.f =Number(scope.f) - 1; 
     } 
     scope.reset = function(){ 
      scope.f = 1; 
     } 
    }, 
    template:"<button ng-click='add()'>more</button>"+ 
      "{{f}}"+ 
      "<button ng-click='remove()'>less</button>&nbsp"+ 
      "<button ng-click='reset()'>reset</button><br><br>" 
    } 

    }) 

Заранее спасибо за помощь.

ответ

1

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

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

app.directive("counterWidget",function(){ 
    return{ 
    restrict:"E", 
    scope:{ 
     startnumber: '=', 
     resetter: '=' 
    }, 
    link:function(scope,elem,attr){ 
     scope.f = attr.startnumber; 
     scope.add = function(){    
      scope.f++ 
     } 
     scope.remove = function(){ 
      scope.f-- 
     } 
     scope.reset = function(){ 
      scope.f = attr.startnumber 
      scope.$parent.triggerReset() 
     } 
     scope.$watch(function(attr) { 
      return attr.resetter 
     }, 
     function(newVal) { 
      if (newVal === true) { 
      scope.f = attr.startnumber; 
      } 
     }) 

    }, 
    template:"<button ng-click='add()'>more</button>"+ 
      "{{f}}"+ 
      "<button ng-click='remove()'>less</button>&nbsp"+ 
      "<button ng-click='reset()'>reset</button><br><br>" 
    } 

    }) 

И в контроллере вы просто добавить небольшую функцию сброса, каждый из директивы наблюдает:

$scope.triggerReset = function() { 
    $scope.reset = true; 
    console.log('reset') 
    $timeout(function() { 
     $scope.reset = false; 
    },100) 
} 

Я бы не усложнять убыли и приращения. ++ и - должно быть хорошо.

Мы создаем глобальную функцию сброса, добавляя атрибут и передавая его в директиву. Затем мы наблюдаем этот атрибут для истинного значения. Всякий раз, когда мы нажимаем reset, мы запускаем функцию в $ parent scope (функция triggerReset()). Эта функция быстро переключает значение $ scope.reset. Любая директива, которая имеет эту привязку в ее атрибуте resetter, будет сброшена на все, что находится в атрибуте startnumber.

Еще одна приятная вещь: перезагрузка влияет только на счетчики, которые вы хотите. Вы даже можете создать несколько групп счетчиков, которые только сбросят счетчики в своей собственной группе. Вам просто нужно добавить триггерную функцию и переменную для каждой группы, для которой вы хотите иметь собственный сброс. Вот демо:

Plunker

EDIT:

Так встал вопрос в комментариях - может ли $ часы функция 'мисс' тумблер? Я сделал небольшое тестирование и лучший ответ, который у меня есть до сих пор, на плункере, если я установил его на 1 мс или даже полностью удалил аргумент времени, $ watch все еще срабатывает. Я также задал этот вопрос сообществу здесь: Can $watch 'miss'?

+0

И всегда может ссылаться на это, вероятно, больше, чем вы хотите знать: http://stackoverflow.com/questions/14049480/what-are-the-nuances-of-scope-prototypal-prototypical-inheritance-in-angularjs – tpie

+0

Что происходит если '$ watch' не поймает изменение значения в 100 мс, как установлено в' timeout'. Имеет ли он возможность неудачи? , или всегда следит за изменением стоимости? .. Простите, если мой вопрос звучит глупо. – dreamer

+0

в любом случае этот ответ велик. оцените усилие – dreamer

0

Вы можете использовать нг-повторение в вашем html.you можно определить количество = 3

<body> 
    <div ng-repeat="index in count"> 
    <counter-widget startnumber=1 ></counter-widget></div> 
</body> 

следовать также связи .Они Объяснил сферу наследования лучшего образом

http://www.sitepoint.com/practical-guide-angularjs-directives-part-two/

Parent Scope (scope: false) - Это случай по умолчанию. Если ваша директива не управляет свойствами родительской области, вам может не понадобиться новая область. В этом случае использование родительской области в порядке.

Child Scope (scope: true) - Создает новый дочерний объект для директивы, которая наследует прототип из родительской области. Если свойства и функции, заданные в области видимости, не относятся к другим директивам и родительским элементам, возможно, вы должны создать новую область с правами пользователя. При этом у вас также есть все свойства и функции области, определенные родителем.

Изолированный масштаб (область: {}) - Это как песочница! Вам нужно это, если директива, которую вы собираетесь строить, является автономной и многоразовой. Ваша директива может создавать множество свойств и функций области, которые предназначены для внутреннего использования и никогда не должны рассматриваться внешним миром. Если это так, лучше иметь изолированный объем. Изолированная область, как и ожидалось, не наследует родительскую область.

+0

i know 'ng-repeat' может использоваться. но я был более заинтересован в том, чтобы узнать о директивах через этот фрагмент. В любом случае это хорошо, что вы указали его. Это поможет другим новичкам – dreamer

0

Это будет лучший подход.

HTML

<body> 
     <counter-widget counter="controllerScopeVariable" ></counter-widget> 
    </body> 

JS

angular.module("myApp",[]) 
    .directive("counterWidget",function(){ 
     return{ 
      restrict:"E", 
      scope:{ 
       counter:'=' 
       }, 
     link:function(scope,elem,attr){ 
      scope.counter = parseInt(scope.counter); 
      scope.add = function(){    
       scope.counter+=1; 
      } 
      scope.remove = function(){ 
       scope.counter-=1; 
      } 
      scope.reset = function(){ 
       scope.counter = 1; 
      } 
      }, 
      template:"<button ng-click='add()'>more</button>"+ 
       "{{f}}"+ 
        "<button ng-click='remove()'>less</button>&nbsp"+ 
       "<button ng-click='reset()'>reset</button><br><br>" 
     } 

    }); 
+1

, пожалуйста, отредактируйте свой ответ, чтобы узнать, почему это лучший подход. Потому что в моем коде я вызываю его из атрибутов и в вашем случае вы используете область для доступа к «начальному номеру». Как это лучший подход и почему? – dreamer

+0

Я не понимаю, что отличает этот ответ. Это написано несколько иначе, но атрибут в значительной степени бесполезен. – tpie

+0

При создании компонентов лучше использовать изолированную область. В этом подходе я использую счетчик, который связан двумя способами между вашим контроллером представления и директивой. Поэтому, если вы хотите получить текущее значение приращения счетчика любого конкретного виджета, просто используйте переменную области видимости, которую вы используете для привязки к вашей директиве. 'var myModue = angular.module ("myApp", []); myModule.controller ("myController", function ($ scope) { $ scope.counter1 = 1; $ scope.counter2 = 1; }); ' ** HTML ** ' <счетчик-виджет счетчик = "счетчик1"> <счетчик-виджет счетчик = "Counter2"> ' –

Смежные вопросы