如何使这个自定义指令更好?

时间:2015-04-23 09:56:17

标签: angularjs angularjs-directive

我正在尝试为计数器小部件实现自定义指令。

我已经能够实现它,但有很多事情我需要一些亮点。

  • 这条指令可以用更好的方式编写吗?
  • 如何以更好的方式使用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>"
    }

  })

提前感谢您的帮助。

3 个答案:

答案 0 :(得分: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)
}

我不会过度复杂递减和递增函数。 ++和 - 应该没问题。

我们通过添加属性并将其传递给指令来创建全局重置功能。然后,我们将该属性视为真正的价值。每当我们点击重置时,我们在$ parent范围内触发一个函数(triggerReset()函数)。该函数快速切换$ scope.reset值。任何在其重置器属性中具有该绑定的指令都将重置为startnumber属性中的任何内容。

另一个好处是重置只会影响你想要的计数器。您甚至可以创建多组计数器,这些计数器仅重置其自己的组中的计数器。您只需要为每个要为其自己重置的组添加触发器功能和变量。 这是演示:

<强> Plunker

修改

所以问题出现在评论中 - $ watch功能可以错过&#39;切换? 我做了一些测试,到目前为止我得到的最佳答案是,如果我将它设置为1ms甚至完全删除时间参数,那么$ watch仍会触发。 我也在这里向社区提出了这个问题:Can $watch 'miss'?

答案 1 :(得分:0)

您可以在html中使用ng-repeat。您可以定义count = 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/

父范围(范围:false) - 这是默认情况。如果您的指令不操作父作用域属性,则可能不需要新作用域。在这种情况下,使用父作用域是可以的。

子范围(范围:true) - 这为原型继承父范围的指令创建了一个新的子范围。如果在作用域上设置的属性和函数与其他指令和父作业无关,则应该创建一个新的子作用域。通过这种方式,您还可以获得父级定义的所有范围属性和函数。

隔离范围(范围:{}) - 这就像一个沙箱!如果要构建的指令是自包含且可重用的,则需要此选项。您的指令可能会创建许多用于内部使用的范围属性和函数,并且永远不会被外界看到。如果是这种情况,最好有一个孤立的范围。正如预期的那样,隔离范围不会继承父范围。

答案 2 :(得分: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>"
       }

     });