我已经仔细阅读了AngularJS关于这个主题的文档,然后摆弄了一个指令。这是小提琴。

以下是一些相关片段:

来自HTML: <窗格bi-title = "标题" title =“{{标题}}>{{文本}}> < /窗格 从窗格指令: scope: {biTitle: '=', title: '@', bar: '='},

有几件事我不明白:

为什么我必须使用“{{title}}”与“@”和“title”与“=”? 我也可以直接访问父范围,而不装饰我的元素与属性? 文档说:“通常情况下,通过表达式将数据从孤立的作用域传递到父作用域是可取的”,但这似乎也适用于双向绑定。为什么表达式路由会更好呢?

我发现另一个小提琴,显示表达式解决方案太:http://jsfiddle.net/maxisam/QrCXh/


当前回答

即使作用域是本地的,就像在您的例子中,您也可以通过属性$parent访问父作用域。假设在下面的代码中,标题是在父作用域上定义的。然后你可以通过$parent.title访问title:

link : function(scope) { console.log(scope.$parent.title) },
template : "the parent has the title {{$parent.title}}"

但是,在大多数情况下,使用属性可以更好地获得相同的效果。

我发现“&”符号的一个例子是在ng-repeat中渲染特殊数据结构的指令中,它用于“通过表达式将数据从隔离作用域传递到父作用域”,很有用(并且不能使用双向数据绑定)。

<render data = "record" deleteFunction = "dataList.splice($index,1)" ng-repeat = "record in dataList" > </render>

渲染的一部分是删除按钮,这里通过&从外部作用域附加一个删除函数很有用。在渲染指令中,它是这样的

scope : { data = "=", deleteFunction = "&"},
template : "... <button ng-click = "deleteFunction()"></button>"

2-way数据绑定,即data =" ="不能被使用,因为delete函数会在每个$digest周期上运行,这是不好的,因为记录会立即被删除,并且永远不会呈现。

其他回答

=方法是双向绑定,它允许你在指令中进行实时更改。当有人在指令外更改变量时,你将在指令内拥有更改的数据,但@ way不是双向绑定。它像文本一样工作。你绑定一次,你就只有它的值。

为了更清楚地理解它,你可以使用这篇很棒的文章:

AngularJS指令作用域'@'和'='

如果您想通过一个现场示例了解更多这是如何工作的。http://jsfiddle.net/juanmendez/k6chmnch/

var app = angular.module('app', []);
app.controller("myController", function ($scope) {
    $scope.title = "binding";
});
app.directive("jmFind", function () {
    return {
        replace: true,
        restrict: 'C',
        transclude: true,
        scope: {
            title1: "=",
            title2: "@"
        },
        template: "<div><p>{{title1}} {{title2}}</p></div>"
    };
});

这个问题已经被折腾得够呛了,但我还是要分享一下,以防其他人也在纠结AngularJS作用域这个可怕的烂摊子。包括=,<,@,&和::。完整的报道可以在这里找到。


=建立双向绑定。更改父对象中的属性将导致子对象中的更改,反之亦然。


<建立单向绑定,父到子。更改父属性将导致子属性的更改,但更改子属性不会影响父属性。


@会将tag属性的字符串值赋给子属性。如果属性包含表达式,则每当表达式计算为不同的字符串时,子属性就会更新。例如:

<child-component description="The movie title is {{$ctrl.movie.title}}" />
bindings: {
    description: '@', 
}

在这里,子作用域中的description属性将是表达式“the movie title is {{$ctrl.movie.”的当前值。Title}}",其中movie是父作用域中的对象。


&有点棘手,事实上似乎没有令人信服的理由去使用它。它允许您在父范围内计算表达式,用子范围内的变量替换参数。一个例子(砰):

<child-component 
  foo = "myVar + $ctrl.parentVar + myOtherVar"
</child-component>
angular.module('heroApp').component('childComponent', {
  template: "<div>{{  $ctrl.parentFoo({myVar:5, myOtherVar:'xyz'})  }}</div>",
  bindings: {
    parentFoo: '&foo'
  }
});

给定parentVar=10,表达式parentFoo({myVar:5, myOtherVar:'xyz'})将计算为5 + 10 + 'xyz',组件将呈现为:

<div>15xyz</div>

你什么时候想使用这个复杂的功能?&经常被人们用来将父作用域中的回调函数传递给子作用域。然而,在现实中,使用'<'来传递函数可以达到同样的效果,这更直接,并且避免了传递参数时笨拙的花括号语法({myVar:5, myOtherVar:'xyz'})。考虑:

使用&:

<child-component parent-foo="$ctrl.foo(bar)"/>
angular.module('heroApp').component('childComponent', {
  template: '<button ng-click="$ctrl.parentFoo({bar:'xyz'})">Call foo in parent</button>',
  bindings: {
    parentFoo: '&'
  }
});

使用<:

<child-component parent-foo="$ctrl.foo"/>
angular.module('heroApp').component('childComponent', {
  template: '<button ng-click="$ctrl.parentFoo('xyz')">Call foo in parent</button>',
  bindings: {
    parentFoo: '<'
  }
});

注意,对象(和数组)是通过引用传递给子作用域的,而不是复制。这意味着即使它是单向绑定,您也在父作用域和子作用域中使用相同的对象。


要查看不同前缀的作用,请打开这个插件。

One-time binding(initialization) using ::

(官方文档) AngularJS的后续版本引入了一次性绑定的选项,其中子作用域属性只更新一次。这样就不需要监视父属性,从而提高了性能。语法与上面不同;要声明一个一次性绑定,在组件标记的表达式前面添加::::::

<child-component 
  tagline = "::$ctrl.tagline">
</child-component>

这将把tagline的值传播到子作用域,而不需要建立单向或双向绑定。注意:如果tagline最初在父作用域中未定义,angular会监视它,直到它发生变化,然后对子作用域中相应的属性进行一次性更新。

总结

下表显示了前缀是如何工作的,这取决于属性是对象、数组、字符串等。

即使作用域是本地的,就像在您的例子中,您也可以通过属性$parent访问父作用域。假设在下面的代码中,标题是在父作用域上定义的。然后你可以通过$parent.title访问title:

link : function(scope) { console.log(scope.$parent.title) },
template : "the parent has the title {{$parent.title}}"

但是,在大多数情况下,使用属性可以更好地获得相同的效果。

我发现“&”符号的一个例子是在ng-repeat中渲染特殊数据结构的指令中,它用于“通过表达式将数据从隔离作用域传递到父作用域”,很有用(并且不能使用双向数据绑定)。

<render data = "record" deleteFunction = "dataList.splice($index,1)" ng-repeat = "record in dataList" > </render>

渲染的一部分是删除按钮,这里通过&从外部作用域附加一个删除函数很有用。在渲染指令中,它是这样的

scope : { data = "=", deleteFunction = "&"},
template : "... <button ng-click = "deleteFunction()"></button>"

2-way数据绑定,即data =" ="不能被使用,因为delete函数会在每个$digest周期上运行,这是不好的,因为记录会立即被删除,并且永远不会呈现。

我们可以简单地使用:-

@:-用于单向数据绑定的字符串值。在一种方式中,数据绑定只能将作用域值传递给指令 =:- for对象值用于双向数据绑定。数据绑定有两种方式,你可以在指令和HTML中改变作用域值。 &:-用于方法和函数。

EDIT

在Angular 1.5及以上版本的组件定义中 有四种不同类型的绑定:

=双向数据绑定:-如果我们改变了值,它会自动更新 <单向绑定:-当我们只想从父作用域读取参数而不更新它时。 @这是字符串参数 &这是为了回调,以防你的组件需要输出一些东西到它的父作用域