30

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

<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 属性也会发生变化。该名称是从父范围(不是组件范围)读取的。

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

= 或 = 表达式 - 在本地范围属性和父范围属性之间设置双向绑定。如果未指定 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 中完成简单的任务(非常适合玩具应用程序,但对于我想要构建的客户端应用程序不是那么好),为什么没有更高级的东西???

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

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

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

4

2 回答 2

66

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

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

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

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

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

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

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

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

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

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

于 2012-10-23T14:53:04.487 回答
33

你很接近..

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' }... 其中=代表双向绑定场景。如果您将其更改=为 a@您会看到它只允许您将字符串作为属性传递给指令。用于从父作用域的&上下文中执行函数。

我希望这会有所帮助。


编辑:这是一个有效的 PLNKR

于 2012-10-23T14:52:08.983 回答