如何将许多值传递给Angularjs指令?

Spe*_*cer 13 javascript angularjs angularjs-directive

我正在通过指令创建一个可重用的html.html会有一些我希望从原始范围传递的变量.通过在指令上声明属性,然后创建隔离范围并捕获它们,可以轻松完成此操作.问题是,对于大量变量,有更好的方法吗?我想过要传递一个像这样的物体{firstAttr: $scope.one, secondAttr: $scope.two...}并将这个物体分开以获得每件物品.这是第一次工作,但双向数据绑定不起作用(即使使用'=').

问题在于绑定的是对象,而不是对象的每个部分.我可以使用指令中的compile函数将每个属性添加到元素中吗?所以:

<mydirective databinding="{one:'first one', two:'second one'}">
Run Code Online (Sandbox Code Playgroud)

将被翻译成:

<mydirective one="first one" two="second one">
Run Code Online (Sandbox Code Playgroud)

这样,通过捕获指令中的属性,我的数据绑定将按预期工作.我将如何完成该设计,还是完全采用另一种方式来实现这一目标?

Sco*_*mas 15

数据绑定指令的想法是一个有趣的,但它不是我这样做的方式,因为我相信你会遇到指令优先级问题,加上它非常非标准的事实,并且会使你的代码很难跟随未来的程序员.有几种方法可以做到这一点,所以我将讨论我使用过的3种不同的解决方案.

解决方案1

如果您只需要单向数据绑定,最简单的解决方案是使用angular的范围.$ eval函数在使用{{}}在其上插入任何简单的范围变量后,对指令内对象的字符串表示形式.字符串表示甚至不必是有效的JSON,因为在下面的示例中您将注意到我没有在对象键周围包含引号.

在视图中:

<div databinding="{one:'first', two:{{scopeVar}}, complex:[1,2, "Hi"]}"></div>
Run Code Online (Sandbox Code Playgroud)

并在JavaScript中:

app.directive('databinding', function () {
   return{
      link: function (scope, elm, attrs) {

        console.debug(scope.$eval(attrs['databinding']));

      }
   }
});
Run Code Online (Sandbox Code Playgroud)

解决方案2

另一种单向数据绑定解决方案是在控制器内创建一个选项对象,并使用"@"(甚至"=")将其传递给指令:

在控制器中:

$scope.options = {one: "first, two: "second"};
Run Code Online (Sandbox Code Playgroud)

在视图中:

<div databinding="options"></div>
Run Code Online (Sandbox Code Playgroud)

并在JavaScript中:

app.directive('databinding', function () {
   return{
      scope: {

        options: "@" //Can also use = here

      },
      link: function (scope, elm, attrs) {

        console.log(scope.options);

      }
   }
});
Run Code Online (Sandbox Code Playgroud)

解决方案3

如果你确实需要双向数据绑定,那么你大部分都不走运,因为没有优雅的方法可以做到这一点.但是,如果您在市场上使用hackish解决方案,您可以使用与解决方案2非常相似的方法完成双向数据绑定,但需要更改选项对象.

不是声明包含简单原始数据类型(如字符串)的选项对象,而是在选项对象中创建一个虚拟对象,然后在其中声明变量.这样做,控制器中范围变量的更改也将在指令内实现,如超时所示.

控制器:

$scope.someScopeVar = "Declared in controller"    

$scope.options = {
  dummy: {
     one: $scope.someScopeVar,
     two: "second"
  }
}

window.setTimeout(function(){

  $scope.someScopeVar = "Changed in controller";

}, 2000)
Run Code Online (Sandbox Code Playgroud)

视图:

<div databinding="options"></div>
Run Code Online (Sandbox Code Playgroud)

指示:

app.directive('databinding', function () {
   return{
      scope: {
        options: "=" //You need to use = with this solution
      },
      link: function (scope, elm, attrs) {

        console.log(scope.options.dummy.one); //Outputs "Declared in controller"

        window.setTimeout(function(){

           console.log(scope.options.dummy.one) //Outputs "Changed in controller"

        }, 5000)

      }
   }
});
Run Code Online (Sandbox Code Playgroud)

此方法有效,因为javascript通过引用传递对象,而基元被复制.通过在对象中嵌套对象,可以保留数据绑定.


Ano*_*oop 1

您可以按如下方式更改指令的范围

.('mydirective ', function(){

   var linker = function(scope, element){
        console.log(scope.one, scope.two);    
   }    
   return {
        link: linker,
        scope: {one:"=", two:"="}
   }    
});
Run Code Online (Sandbox Code Playgroud)