Angularjs 如何使这个定制指令更好?

Angularjs 如何使这个定制指令更好?,angularjs,angularjs-directive,Angularjs,Angularjs Directive,我正在尝试为计数器小部件实现自定义指令 我已经能够实现它,但是有很多事情我需要一些启发 该指令是否可以用更好的方式编写 如何更好地使用作用域:(隔离作用域)? 单击任何重置按钮,我希望所有的startnumber都重置为“1” 作用域从何处继承?它从被调用的元素继承吗 HTML代码片段 <body> <counter-widget startnumber=1 ></counter-widget> <counter-widget startnu

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

我已经能够实现它,但是有很多事情我需要一些启发

  • 该指令是否可以用更好的方式编写
  • 如何更好地使用
    作用域:
    (隔离作用域)?
  • 单击任何重置按钮,我希望所有的
    startnumber
    都重置为“1”
  • 作用域从何处继承?它从被调用的元素继承吗
    
HTML代码片段

<body>
  <counter-widget startnumber=1 ></counter-widget>
  <counter-widget startnumber=1 ></counter-widget>
  <counter-widget startnumber=1 ></counter-widget>
</body>
  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>"
    }

  })

JS片段

<body>
  <counter-widget startnumber=1 ></counter-widget>
  <counter-widget startnumber=1 ></counter-widget>
  <counter-widget startnumber=1 ></counter-widget>
</body>
  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>"
    }

  })
angular.module(“myApp”,[])
.directive(“counterWidget”,function()){
返回{
限制:“E”,
范围:{
},
链接:功能(范围、要素、属性){
scope.f=attr.startnumber;
scope.add=函数(){
范围f=数量(范围f)+1;
}
scope.remove=函数(){
范围f=编号(范围f)-1;
}
scope.reset=函数(){
范围f=1;
}
},
模板:“更多”+
“{{f}}”+
“更少”+
“重置

” } })

提前谢谢你的帮助

您可以在html中使用ng repeat。您可以定义count=3

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

另外,他们还以更好的方式解释了作用域继承

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

子作用域(作用域:true)–这将为指令创建一个新的子作用域,该指令通常从父作用域继承。如果在作用域上设置的属性和函数与其他指令和父级无关,则可能应该创建一个新的子作用域。有了它,您还拥有父级定义的所有作用域属性和函数


隔离作用域(作用域:{})——这就像一个沙箱!如果要构建的指令是自包含且可重用的,则需要使用此命令。您的指令可能正在创建许多供内部使用的作用域属性和函数,外部世界永远不会看到它们。如果是这种情况,最好有一个独立的作用域。正如预期的那样,隔离作用域不会继承父作用域。

这将是一种更好的方法

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>"
       }

     });
angular.module(“myApp”,[])
.directive(“counterWidget”,function()){
返回{
限制:“E”,
范围:{
计数器:'='
},
链接:功能(范围、要素、属性){
scope.counter=parseInt(scope.counter);
scope.add=函数(){
范围.计数器+=1;
}
scope.remove=函数(){
范围.计数器-=1;
}
scope.reset=函数(){
scope.counter=1;
}
},
模板:“更多”+
“{{f}}”+
“更少”+
“重置

” } });
首先,传入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>"
    }

  })
我不会使减量和增量函数过于复杂化而且应该没事

我们通过添加一个属性并将其传递给指令来创建全局重置函数。然后,我们观察该属性的真实值。无论何时单击reset,都会触发$parent作用域中的函数(triggerReset()函数)。该函数可快速切换$scope.reset值。任何在其reset属性中具有该绑定的指令都将重置为startnumber属性中的任何内容

另一件好事是,重置只会影响您希望它的计数器。您甚至可以创建多个计数器组,这些计数器组只重置自己组中的计数器。您只需要为每个想要重置的组添加一个触发器函数和变量。 以下是演示:

编辑:

因此,评论中提出了一个问题:$watch函数是否会“错过”切换? 我做了一些测试,到目前为止,我得到的最好答案是,在plunker上,如果我将其设置为1ms,甚至完全删除time参数,$watch仍然会触发。
我还在这里向社区提出了这个问题:

请编辑您的答案,以说明为什么这是一个更好的方法。因为,在我的代码中,我是从属性调用它的,在您的例子中,您使用的是范围来访问
startnumber
。这是一个怎样更好的方法?为什么?我并没有看到这个答案有什么不同。它的编写方式略有不同,但属性几乎毫无用处。在创建组件时,最好使用隔离作用域。在这种方法中,我使用的计数器是视图控制器和指令之间的双向绑定。因此,如果您想获取任何特定小部件的当前递增计数器值,只需使用用于将其绑定到指令的范围变量即可var myModue=angular.module(“myApp”,[]);controller(“myController”,函数($scope){$scope.counter1=1;$scope.counter2=1;});'HTML“”我知道可以使用
ng repeat
。但我更热衷于通过这段代码学习指令。不管怎样,你指出它是件好事。它将帮助其他新手,你可以随时参考这段代码,了解的可能比你想知道的更多:如果“$watch”没有捕捉到指令的变化,会发生什么