【问题标题】:Need some examples of binding attributes in custom AngularJS tags需要一些自定义AngularJS标签中绑定属性的例子
【发布时间】:2012-10-13 12:19:35
【问题描述】:

我正在尝试创建类似于以下内容的自定义标签:

<mytag type="Big" />

其中 type 是绑定到组件的属性。以这样的方式将文本设置在标签中,如下所示:

<label>{{type}}</label>

...(其他组件)...

正如文档所说,我有一个设置默认类型的控制器:

$scope.type = "Small";

所以如果我使用没有属性类型的标签仍然会被设置。

我正在尝试使用指令进行绑定:

angular.module('TestPage',[])
      .directive('mytag',function() {
          return {
              restrict: 'E',
              templateUrl: 'component.html',
              scope: {
                  type: '='
              }
          }
      });

请注意,我的组件模板中确实有适当的 ng-app 设置 (ng-app="TestPage")。

我的问题是与类型的绑定似乎并没有真正绑定任何东西。

我已阅读有关如何使用指令将变量绑定到组件的文档。根据文档,您可以在范围内进行此类绑定。范围显然可以包含一个“对象哈希”(不管那是什么!),它创建了一个称为“隔离范围”(???)的东西。此类范围可以通过以下方式表示“本地属性”:

@ 或 @attr - 将本地范围属性绑定到 DOM 属性。结果始终是一个字符串 因为 DOM 属性是字符串。如果未指定 attr 名称,则本地名称和 属性名称相同。给定范围的小部件定义:{ localName:'@myAttr'},然后小部件范围属性 localName 将反映 hello {{name}} 的插值。随着 name 属性的变化,小部件范围上的 localName 属性也会发生变化。名称是从父作用域(不是组件作用域)读取的。

啊???这与正确的绑定语法有什么关系?

= 或 =expression - 在本地范围属性和父级之间设置双向绑定 范围属性。如果未指定 attr 名称,则本地名称和属性名称相同。 给定范围的widget定义:{localModel:'=myAttr'},那么widget范围属性localName将在父范围上反映parentModel的值。对 parentModel 的任何更改都将反映在 localModel 中,而对 localModel 的任何更改都将反映在 parentModel 中。

对不起?这里在说什么???

& 或 &attr - 提供一种在父作用域的上下文中执行表达式的方法。如果不 指定 attr 名称,则本地名称和属性名称相同。给定 和范围的小部件定义:{ localFn:'increment()' }, 然后隔离范围属性 localFn 将指向 increment() 表达式的函数包装器。通常希望通过表达式将数据从隔离作用域传递到父作用域,这可以通过将局部变量名称和值的映射传递到表达式包装器 fn 来完成。例如,如果表达式是 increment(amount),那么我们可以通过调用 localFn 来指定数量值 localFn({amount: 22})。

现在我完全糊涂了!你有小部件标签和某种相关的功能,我必须写我才能进行绑定???我想要的只是将值绑定到标签标签!

我从文档 (http://docs.angularjs.org/guide/directive) 中复制了上面的文字,以说明这一点:这个文档读起来像旧的 UNIX 文档:对已经了解系统的人非常有用,但对初学者没有太大帮助试图发展真正的专业知识。所有的教程都展示了如何在 AngularJS 中完成简单的任务(非常适合玩具应用程序,但对于我想要构建的客户端应用程序不是那么好),为什么没有更高级的东西???

好的,是时候让我更有建设性了。

有人可以提供一些很好的简单示例,说明如何执行本文档极难描述的各种绑定吗???显示这些范围语句的正确语法的示例以及它们如何返回到添加到自定义标签的属性的描述(用简单的英语)???

感谢您的耐心等待,并提前感谢您提供的任何帮助。

【问题讨论】:

  • 我已经发了一个blog post 关于这个:我认为这个主题应该在官方教程中 - 拥有可重用组件是一个杀手级功能。我为此提交了pull request
  • 遇到这些挫折的不止您一个人。我当然有过这种感觉。不过,对于那些读过这篇文章并有类似感受的人来说,只是一句鼓励的话:坚持下去。我不是 Angular 的粉丝或爱好者,但是一旦我成功了,我就真的开始享受用它来构建了。 (对于 UNIX 也是如此!;)

标签: angularjs


【解决方案1】:

当我第一次接触 Angular 时,我也对这个文档有点挣扎,但我会尝试为你澄清一些事情。首先,当使用这个scope 属性时,它会创建一个“隔离范围”。这意味着它不会从父作用域继承任何属性,因此您不必担心作用域内的任何冲突。

现在,'@' 表示法意味着属性中的评估值将自动绑定到指令的范围内。因此,&lt;my-directive foo="bar" /&gt; 最终将具有一个名为foo 的属性,该属性包含字符串“bar”。您也可以执行类似&lt;my-directive foo="{{bar}}" 的操作,然后{{bar}} 的评估值将绑定到范围。由于属性始终是字符串,因此在使用此表示法时,您始终会在范围内得到该属性的字符串。

'=' 符号基本上提供了一种将对象传递到指令中的机制。它总是从指令的父范围中提取它,所以这个属性永远不会有{{}}。因此,如果您有&lt;my-directive foo="bar" /&gt;,它将把$scope.bar 中的任何内容绑定到您指令范围的foo 属性中的指令中。您在自己的范围内对 foo 所做的任何更改都将反映在父范围内的 bar 中,反之亦然。

我几乎没有像其他人那样使用“&”符号,所以我对它的了解不如这两个。据我了解,它允许您从父范围的上下文中评估表达式。所以如果你有类似&lt;my-directive foo="doStuff()" /&gt; 的东西,每当你在指令中调用 scope.foo() 时,它都会在指令的父作用域中调用 doStuff 函数。我相信你可以用这个做更多的事情,但我对这一切并不熟悉。也许其他人可以更详细地解释这一点。

如果只在作用域中设置符号,它将使用与属性相同的名称来绑定到指令作用域。例如:

scope: {
   foo1: '@',
   foo2: '=',
   foo3: '&'
}

当包含指令时,需要有属性 foo1、foo2 和 foo3。如果您希望范围内的属性与属性名称不同,则可以在符号之后指定。所以,上面的例子是

scope: {
   foo1: '@bar1',
   foo2: '=bar2',
   foo3: '&bar3'
}

当包含指令时,需要有属性 bar1、bar2 和 bar3,它们将分别绑定在属性 foo1、foo2 和 foo3 下的范围内。

我希望这会有所帮助。随意提出问题,我可以澄清我的答案。

【讨论】:

  • 感谢这篇文章。我现在对各种符号及其工作原理有了更深入的了解。这很有帮助。
  • 我想知道为什么很难找到说明 = 用于传递对象的文档。我读过的所有文档都说 = 用于绑定到模型值,这不太通用.它不需要是模型值 - 任何表达式都可以。
【解决方案2】:

你很接近..

app.directive('mytag',function() {
    return {
        restrict: 'E',
        template: '<div>' +
            '<input ng-model="controltype"/>' + 
            '<button ng-click="controlfunc()">Parent Func</button>' + 
            '<p>{{controlval}}</p>' + 
         '</div>',
        scope: {
            /* make typeattribute="whatever" bind two-ways (=)
            $scope.whatever from the parent to $scope.controltype
            on this directive's scope */
            controltype: '=typeattribute',
            /* reference a function from the parent through
               funcattribute="somefunc()" and stick it our
               directive's scope in $scope.controlfunc */
            controlfunc: '&funcattribute',
            /* pass a string value into the directive */
            controlval: '@valattribute'
        },
        controller: function($scope) {                  
        }
    };
});

  <div ng-controller="ParentCtrl">
       <!-- your directive -->
       <mytag typeattribute="parenttype" funcattribute="parentFn()" valattribute="Wee, I'm a value"></mytag>
       <!-- write out your scope value -->
       {{parenttype}}
  </div>


  app.controller('ParentCtrl', function($scope){ 
       $scope.parenttype = 'FOO';
       $scope.parentFn = function() {
           $scope.parenttype += '!!!!';
       }
  });

神奇之处主要在于指令定义中的scope: 声明。有任何scope: {} 将“隔离”父级的范围,这意味着它拥有自己的范围......没有它,它将使用父级的范围。其余的魔法在作用域的属性中:scope: { 'internalScopeProperty' : '=externalAttributeName' }... 其中= 代表一种双向绑定方案。如果您将= 更改为@,您会看到它只允许您将字符串作为属性传递给指令。 &amp; 用于从父作用域的上下文中执行函数。

希望对你有帮助。


编辑:Here is a working PLNKR

【讨论】:

  • 感谢您的这篇文章。示例代码非常有帮助。不幸的是,我似乎无法复制您的示例。我确实有一些问题:指令声明中的空“控制器”函数似乎没有做任何事情。和app.controller中声明的函数有关系吗?另外: app 究竟是如何声明的?我使用 angular.module() 声明了该指令。你对“app”使用类似的说法吗?
  • app 将是您的模块...var app = angular.module('myApp', []); ...抱歉,这是主模块的标准变量名称。
  • 空的controller 函数是指令的控制器。或者...template 中内容的控制器。
  • 指令的controller 部分中的$scope 是特定于该指令的范围,它是在指令声明的scope 参数中定义的范围。 `
  • 抱歉,Blesh,因为我对 Javascript 变量一无所知。我的专长是 Java、C++ 和 C# 编程。我不是 Javascript 专家。我也做了一些 Actionscript 编程,但 Actionscript 比 Javascript 更“完整”......无论如何,感谢您的澄清。一个问题:为了使用 AngularJS,必须是 Javascript 专家吗?我非常擅长 jQuery,而无需了解 Javascript 内部结构。 AngularJS 是这样吗?还是必须是真正的 Javascript 专家才能很好地使用它?
猜你喜欢
  • 2018-01-10
  • 2011-07-19
  • 2017-05-21
  • 2021-01-19
  • 1970-01-01
  • 2015-09-24
  • 2019-07-23
  • 1970-01-01
  • 2021-06-11
相关资源
最近更新 更多