这是一些相关的摘要:
来自HTML:
<pane bi-title="title" title="{{title}}">{{text}}</pane>
来自窗格指令:
scope: { biTitle: '=', title: '@', bar: '=' },
有几件事我不明白:
为什么必须将
"{{title}}"
和'@'
结合使用,将"title"
和'='
和q4312079q结合使用? “通常希望通过表达式将数据从隔离的范围传递到父范围”,但这似乎也可以与双向绑定一起使用。为什么表达途径会更好?#1 楼
为什么必须将'{{title}}'与'@'一起使用,并将“ title”与'='一起使用?到DOM属性的评估值。如果使用
title=title1
或title="title1"
,则DOM属性“ title”的值就是字符串title1
。如果使用title="{{title}}"
,则DOM属性“ title”的值是{{title}}
的内插值,因此该字符串将是当前设置为父范围属性“ title”的任何值。由于属性值始终是字符串,因此在使用@。=将本地/指令范围属性绑定到父范围属性时,在该指令的作用域中,此属性总是以字符串值结尾。因此,使用=,您可以将父模型/范围属性名称用作DOM属性的值。您不能将
{{}}
与=一起使用。通过@,您可以执行
title="{{title}} and then some"
之类的操作-对{{title}}进行插值,然后将字符串“ and them some”与其连接。最终的串联字符串是local / directive范围属性所获得的。 (您不能使用=只能使用@。)如果使用@,则需要在链接函数中使用该值,则需要使用
attr.$observe('title', function(value) { ... })
。例如,if(scope.title == "...")
无法正常工作。请注意,这意味着您只能异步访问此属性。如果仅在模板中使用值,则无需使用$ observe()。例如,
template: '<div>{{title}}</div>'
。带=,您不需要使用$ observe。是的,但只有在不使用隔离范围的情况下,才可以使用带有属性的属性?
从指令
scope: { ... }
删除此行,然后您的指令将不会创建新的作用域。它将使用父范围。然后,您可以直接访问所有父范围属性。
该文档说:“通常希望通过表达式将数据从隔离范围传递到父范围”,但这似乎也可以与双向绑定一起使用。为什么表达式路由会更好?
是的,双向绑定允许本地/指令范围和父范围共享数据。 “表达式绑定”允许指令调用由DOM属性定义的表达式(或函数)-您还可以将数据作为参数传递给表达式或函数。因此,如果您不需要与父级共享数据(只想调用父级作用域中定义的函数),则可以使用&语法。
另请参见
Lukas的隔离范围博客文章(涵盖@,=,&)
dnc253对@和=的解释
我的博客关于范围的类似答案-指令部分(位于底部,在“摘要”部分的前面)具有隔离范围及其父范围的图片-指令范围对一个属性使用@,对另一个属性使用= > angularJS中&vs @和=之间有什么区别
评论
呵呵,这是一个非常奇怪的行为,尤其是当不使用插值而只是尝试传递字符串时。显然,拉取请求确实已合并到开发版本中,并且在1.1.5和1.2.0 RC版本中。擅长于解决这种非常不直观的行为!
–易卜拉欣
2013年9月25日20:36在
写“ @”或“ =”比写“ eval-dom”或“ parent-scope”或任何其他人类可读文本更加清晰。好的设计决策。
–丹
2014年3月3日在16:57
@('at')复制'ATtribute'的值。 =('等于')等于说键等于您的表情。至少,这就是我保持海峡的方式。
–马特·德克里(Matt DeKrey)
14年6月25日在12:18
您确定=仅适用于父范围属性吗?任何表达式似乎都可以工作-不仅限于父范围属性。
–乔纳森·阿基诺(Jonathan Aquino)
2014-10-15 22:40
@JonathanAquino,可以,但是@更合适-使用foo =“ {{1 + 1}}”-因为我们这里不需要双向数据绑定。我在上面的注释中试图指出的一点是,仅当指令需要双向数据绑定时才应使用=。使用@或&否则。
– Mark Rajcok
2014年10月17日在18:15
#2 楼
这里有很多很好的答案,但是我想对证明对我有用的@
,=
和&
绑定之间的差异提供自己的看法。从父作用域到指令的隔离作用域,通过元素的属性:@绑定用于传递字符串。
这些字符串支持内插值的
{{}}
表达式。 例如:
。插值表达式是根据
指令的父范围求值的。
=绑定用于双向模型绑定。父范围中的模型
链接到指令隔离范围中的模型。对一个模型的更改会影响另一个模型,反之亦然。
&绑定用于将方法传递到指令的作用域中,以便可以在指令中调用它。该方法已预绑定到指令的父作用域,并支持参数。例如,如果方法在父范围内是hello(name),则为了从指令内部执行该方法,必须
调用$ scope.hello({name:'world'})
我发现,通过简短描述引用作用域绑定,可以更容易地记住这些差异:
@
属性字符串绑定=
双向模型绑定&
回调方法绑定符号还使范围变量在指令的实现内部表示什么变得更清楚: >
@
模型=
方法按实用性排序(无论如何对我来说): > =
@
&
评论
实际上,“&”确实支持以下形式的参数(或更确切地说是本地变量):callback({foo:“ some value”}),然后可以使用
–新开发人员
2015年3月20日15:29
应该接受答案。这是一篇简明扼要的文章,内容相同,但有一些代码示例:umur.io/…
–凯文
15年4月28日在15:37
&不是“回调方法绑定”,而是Angular表达式绑定。一个特殊但并非唯一的示例是表达式callback(argument)。这仍然与回调本身不同。
–德米特里·扎伊采夫(Dmitri Zaitsev)
2015年11月12日下午4:22
尽管我喜欢较高排名的答案的确定性,但我发现此答案产生了更大的影响,并且阅读此答案后,我对上一个答案有了更多的了解。
–rbnzdave
15年11月24日在18:51
我同意以上评论,此答案对于问题更明确,明确和有用。它详细解释了您可以使用的信息。
–user3125823
16 Mar 8 '16 at 15:14
#3 楼
=
表示双向绑定,因此对父作用域的变量的引用。这意味着,当您更改指令中的变量时,它也会在父作用域中也被更改。 br />据我所知,@
也应该工作。 <pane bi-title="{{title}}" title="{{title}}">{{text}}</pane>
将收到父范围变量值,该值可以在指令中更改。如果需要更改父范围中的多个变量,则可以在指令中在父范围上执行一个函数(或通过服务传递数据)。
评论
是的,我明白这一点,请看问题中的小提琴。但是不清楚的部分呢?
– iwein
2012年12月27日在7:25
问题是{{}}不能与=一起使用。 =不会被评估,但字符串将直接用作属性名称。感谢你的回答!
– iwein
2012-12-30 13:06
我不认为=仅适用于父作用域中的变量。它适用于任何表达式(例如1 + 1)。
–乔纳森·阿基诺(Jonathan Aquino)
2014年10月15日在22:42
@JonathanAquino你是对的,它评估表达式。恕我直言,这实际上很奇怪,我不会那样使用。正是这种巧妙的技巧使指令作用域一开始让我很难理解。
– iwein
15年5月16日在12:23
我是唯一认为这个答案是错误的人! “ =”表示期望角度为JavaScript表达式,并且如果传递了范围变量,则将进行双向映射。而@平均角度期望一个String等等。实际上,如果将@与{{}}结合使用,则将克隆变量的值。但这不是@的定义!
–吕克·杜赞(Luc DUZAN)
2015年5月21日在7:34
#4 楼
如果您想通过实际示例了解更多信息。 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>"
};
});
评论
问题和最佳答案中有几个示例。这增加了什么?
– iwein
2014年11月24日9:00
@iwein,它增加了清晰度。如果我能理解和吸收功能齐全的示例,则不需要此站点。
–托尼·恩尼斯(Tony Ennis)
2015年1月9日在15:47
胡安,也许解决你的错字? “ transclude”拼写错误。更好的是,将它(不会导致问题的其他所有原因,例如“替换”)删除,这样您的解决方案就更加简单明了。范例为+1。
–托尼·恩尼斯(Tony Ennis)
2015年1月9日15:49
谢谢@AnikISlamAbhi的编辑。我想贡献更多,很高兴有人发现我的样品有帮助。那是主要目的。
– Juan Mendez
2015年2月10日在21:54
示例不完整。在演示中,您仅更改双向值。您甚至没有试图更改具有隔离范围的值。因此,它没有正确演示作用域在指令中的工作方式。
– Sudarshan_SMD
18年4月11日在6:18
#5 楼
@
作为字符串获取这不会创建任何绑定。您只是得到以字符串形式传递的单词
=
2种方式绑定控制器所做的更改将反映在指令,反之亦然
&
这一点有所不同,因为作用域获得了一个函数,该函数返回传入的对象。小提琴应该弄清楚这一点。调用此getter函数后,生成的对象的行为如下:传递了函数:如果调用了非函数,则在父(控制器)闭包中执行该函数
如果传递了非函数:只需获取没有绑定的对象的本地副本
这个小提琴应该演示它们如何工作。请特别注意名称中带有
get...
的范围函数,以期希望更好地理解我对&
的含义#6 楼
可以在指令中添加范围的三种方法:父范围:这是默认的范围继承。
指令及其父级(位于其内部的控制器/指令)范围是相同的。
因此,对指令内范围变量所做的任何更改也会反映在父级控制器中。您无需指定它,因为它是默认设置。指令为true。
这里,如果您更改指令中的范围变量,它将不会反映在父范围中,但是,如果您更改了范围变量的属性,则它会反映在父范围中。实际修改了父级的范围变量。
示例,
app.directive("myDirective", function(){
return {
restrict: "EA",
scope: true,
link: function(element, scope, attrs){
scope.somvar = "new value"; //doesnot reflect in the parent scope
scope.someObj.someProp = "new value"; //reflects as someObj is of parent, we modified that but did not override.
}
};
});
隔离范围:使用当您要创建不从控制器范围继承的范围时。
在创建插件时会发生这种情况,因为该指令可以通用,因为它可以放置在任何HTML中,并且不受其父作用域的影响。您不希望与父范围进行任何交互,则只需将范围指定为空对象即可。例如,
scope: {} //this does not interact with the parent scope in any way
大多数情况并非如此,因为我们需要与父作用域进行一些交互,因此我们希望某些值/更改能够通过。 />为此,我们使用:
1. "@" ( Text binding / one-way binding )
2. "=" ( Direct model binding / two-way binding )
3. "&" ( Behaviour binding / Method binding )
@表示控制器范围的更改将反映在指令范围内,但是如果您在指令范围,控制器范围变量将不会受到影响。
@始终希望映射的属性是一个表达式。这个非常重要;因为要使“ @”前缀起作用,我们需要将属性值包装在{{}}中。
=是双向的,因此如果您在指令范围内更改变量,则控制器范围变量也会受到影响
&用于绑定控制器范围方法,以便在需要时我们可以从指令中调用它
这里的优点是变量名称在控制器作用域和指令作用域中不必相同。
例如,指令作用域具有变量“ dirVar”,该变量与控制器作用域的变量“ contVar”同步。这为指令提供了强大的功能和通用性,因为一个控制器可以与变量v1同步,而另一个使用同一指令的控制器可以要求dirVar与变量v2同步。
下面是用法示例:
指令和控制器是:
var app = angular.module("app", []);
app.controller("MainCtrl", function( $scope ){
$scope.name = "Harry";
$scope.color = "#333333";
$scope.reverseName = function(){
$scope.name = $scope.name.split("").reverse().join("");
};
$scope.randomColor = function(){
$scope.color = '#'+Math.floor(Math.random()*16777215).toString(16);
};
});
app.directive("myDirective", function(){
return {
restrict: "EA",
scope: {
name: "@",
color: "=",
reverse: "&"
},
link: function(element, scope, attrs){
//do something like
$scope.reverse();
//calling the controllers function
}
};
});
和html(注意@和=的区别):
<div my-directive
class="directive"
name="{{name}}"
reverse="reverseName()"
color="color" >
</div>
这里是到博客的链接,描述得很好。
评论
&既不是“行为绑定”也不是“方法绑定”,它是Angular表达式绑定。
–德米特里·扎伊采夫(Dmitri Zaitsev)
2015年11月12日下午4:23
#7 楼
简单地,我们可以使用:-@:-表示字符串绑定的一种方法。以一种方式进行数据绑定时,您只能将范围值传递给指令
=:-用于双向方式数据绑定的对象值。通过两种方式的数据绑定,您可以在指令以及html中更改作用域值。
&:-用于方法和函数。
编辑
在Angular 1.5及更高版本的组件定义中
有四种不同类型的绑定:
=
双向数据绑定:-如果更改值,它将自动更新<
单向绑定:-当我们只想阅读时@
这是用于字符串参数&
这是用于回调,以防您的组件需要向其父作用域输出某些内容#8 楼
我创建了一个包含Angular代码的HTML文件,演示了它们之间的区别:<!DOCTYPE html>
<html>
<head>
<title>Angular</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js"></script>
</head>
<body ng-app="myApp">
<div ng-controller="myCtrl as VM">
<a my-dir
attr1="VM.sayHi('Juan')" <!-- scope: "=" -->
attr2="VM.sayHi('Juan')" <!-- scope: "@" -->
attr3="VM.sayHi('Juan')" <!-- scope: "&" -->
></a>
</div>
<script>
angular.module("myApp", [])
.controller("myCtrl", [function(){
var vm = this;
vm.sayHi = function(name){
return ("Hey there, " + name);
}
}])
.directive("myDir", [function(){
return {
scope: {
attr1: "=",
attr2: "@",
attr3: "&"
},
link: function(scope){
console.log(scope.attr1); // =, logs "Hey there, Juan"
console.log(scope.attr2); // @, logs "VM.sayHi('Juan')"
console.log(scope.attr3); // &, logs "function (a){return h(c,a)}"
console.log(scope.attr3()); // &, logs "Hey there, Juan"
}
}
}]);
</script>
</body>
</html>
#9 楼
这个问题已经被打死了,但是我还是会分享这个问题,以防其他人为AngularJS范围的可怕混乱而苦恼。这将覆盖=
,<
,@
,&
和::
。完整的文章可以在这里找到。 =
建立双向绑定。更改父级中的属性将导致子级中的变化,反之亦然。在父级中更改属性将导致子级更改,但是更改子级属性不会影响父级属性。<
将为子级属性分配字符串值标签属性。如果属性包含表达式,则子表达式在表达式计算为其他字符串时更新。例如:<child-component description="The movie title is {{$ctrl.movie.title}}" />
bindings: {
description: '@',
}
此处,子范围中的
@
属性将是表达式description
的当前值,其中"The movie title is {{$ctrl.movie.title}}"
是父范围中的对象。 movie
有点棘手,实际上似乎没有令人信服的理由去使用它。它允许您在父作用域中评估表达式,用子作用域中的变量替换参数。一个例子(plunk):<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'})
,并且该组件将呈现为: br /> <div>15xyz</div>
您何时想使用此复杂功能?人们经常使用
5 + 10 + 'xyz'
将父范围内的回调函数传递给子范围。然而,实际上,通过使用'<'传递函数可以实现相同的效果,该效果更直接,并且避免了笨拙的花括号语法传递参数(&
)。考虑:使用
{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: '<'
}
});
请注意,对象(和数组)是通过引用传递给子作用域的,而不是复制的。这意味着即使是单向绑定,您也在父范围和子范围中使用相同的对象。
要查看运行中的不同前缀,请打开此插件。官方文档]
较新版本的AngularJS引入了具有一次性绑定的选项,其中子范围属性仅更新一次。通过消除监视父属性的需要,可以提高性能。语法与上面不同。要声明一次性绑定,请在组件标记的表达式前面添加
<
:建立单向或双向绑定。注意:如果::
在父作用域中最初是::
,则angular将对其进行监视直到更改,然后对子作用域中的相应属性进行一次性更新。 摘要
下表显示了前缀如何工作,具体取决于属性是对象,数组,字符串等。
#10 楼
=方法是2向绑定,它使您可以在指令中进行实时更改。当某人从指令中更改该变量时,您将在指令中包含该更改的数据,但是@ way不是双向绑定。它像文本一样工作。绑定一次,您将只拥有它的值。要更清楚地了解它,可以使用以下精彩文章: '
#11 楼
@ local scope属性用于访问在指令外部定义的字符串值。=如果需要在外部范围和指令的隔离范围之间创建双向绑定,则可以使用=字符。
&局部作用域属性允许指令的使用者传递该指令可以调用的函数。
请仔细检查下面的链接,使您对示例有清晰的了解。我发现它非常有用,因此考虑共享它。
http://weblogs.asp.net / dwahlin / creating-custom-angularjs-directives-part-2-isolate-scope
#12 楼
即使在作用域是本地作用域(如您的示例)中,您也可以通过属性$parent
访问父作用域。在下面的代码中,假设在父作用域上定义了title
。然后,您可以将标题作为$parent.title
进行访问:我发现“&”符号用于“将表达式从隔离的范围内通过表达式传递到父范围”,这很有用(并且不能使用双向数据绑定),它用于呈现特殊的指令。 ng-repeat内部的数据结构。link : function(scope) { console.log(scope.$parent.title) },
template : "the parent has the title {{$parent.title}}"
渲染的一部分是删除按钮,这里通过&从外部作用域附加delete函数很有用。在渲染指令内部,它看起来像
<render data = "record" deleteFunction = "dataList.splice($index,1)" ng-repeat = "record in dataList" > </render>
2路数据绑定,即
data = "="
无法使用,因为删除功能会在每个$digest
周期上运行,这不好,因为该记录将立即删除,并且从不呈现。#13 楼
我在小提琴中实现了所有可能的选项。它处理所有选项:
scope:{
name:'&'
},
scope:{
name:'='
},
scope:{
name:'@'
},
scope:{
},
scope:true,
https://jsfiddle.net/ rishulmatta / v7xf2ujm
#14 楼
它们之间的主要区别只是@ Attribute string binding
= Two-way model binding
& Callback method binding
#15 楼
@
和=
查看其他答案。 了解
&
TL; DR; &
从父级获取表达式(不仅像其他答案中的示例所示的函数),并将其设置为调用该表达式的指令中的函数。并且该函数可以通过将变量传递给对象来替换表达式的任何变量(甚至函数名)。 解释
&
是一个表达式引用,这意味着如果您在指令中传递类似<myDirective expr="x==y"></myDirective>
的东西,则
expr
将是一个函数,该函数将调用表达式,例如:function expr(){return x == y}
。 因此在指令的html
<button ng-click="expr()"></button>
中将调用该表达式。在指令的js中,仅$scope.expr()
也会调用该表达式。该表达式将被父级的$ scope.x和$ scope.y调用。
您可以覆盖参数! br />如果通过电话进行设置,例如
<button ng-click="expr({x:5})"></button>
,然后将使用您的参数
x
和父级的参数y
调用表达式。您可以同时覆盖这两个表达式。父表达式(例如
<button ng-click="functionFromParent({x:5})"></button>
)并用您指定的参数替换可能的值,在这种情况下为<myDirective functionFromParent="function1(x)"></myDirective>
。甚至使用函数替换:x
。它只是一个表达式,无论是一个函数还是多个函数,还是只是比较,都没有关系。并且您可以替换该表达式的任何变量。
<myDirective functionFromParent="function1(x) + 5"></myDirective>
调用<myDirective functionFromParent="function1(x) + z"></myDirective>
<button ng-click="functionFromParent({x:5, z: 4})"></button>
调用<button ng-click="functionFromParent({function1: myfn, x:5, z: 4})"></button>
父级已定义$ scope.function1,$ scope.x,$ scope.y:
父级模板:
<myDirective expr="x==y"></myDirective>
<button ng-click="expr()"></button>
调用$scope.x==$scope.y
<button ng-click="expr({x: 5})"></button>
调用5 == $scope.y
<button ng-click="expr({x:5, y:6})"></button>
调用5 == 6
指令将$ scope.myFn作为函数:<myDirective expr="function1(x) + y"></myDirective>
调用<button ng-click="expr()"></button>
#16 楼
为什么必须在“ @”中使用“ {{title}}”,而在“ =”中使用“ title”?
当您使用{{title}}时,只有父范围值将传递到指令视图并进行评估。这仅限于一种方式,这意味着更改不会反映在父范围中。如果要将子指令中所做的更改也反映到父作用域中,则可以使用“ =”。这是两种方法。
我也可以直接访问父范围,而不用属性装饰我的
元素吗?当指令中具有scope属性(scope:{})时,您将不再能够直接访问父范围。但是仍然可以通过scope。$ parent等访问它。如果从指令中删除范围,则可以直接访问它。
文档说:“通常希望传递数据从
通过表达式的隔离范围到父范围”,但是该
似乎也可以与双向绑定一起使用。为什么
表达途径会更好?
它取决于上下文。如果要使用数据调用表达式或函数,请使用&,如果要共享数据,则可以使用biderectional方式,并使用'='
。到以下链接的指令:
AngularJS –隔离范围– @ vs = vs&
http://www.codeforeach.com/angularjs/angularjs-isolated-scopes- vs-vs
#17 楼
@属性字符串绑定(单向)=双向模型绑定
和回调方法绑定
#18 楼
@将本地/定向范围属性绑定到DOM属性的评估值。=将本地/定向范围属性绑定到父范围属性。
&绑定用于将方法传递到指令的范围内,以便可以在指令中调用它。
@属性字符串绑定
=双向模型绑定
&回调方法绑定
评论
有道理。研究和寻找答案的能力很重要。stackoverflow.com/questions/14908133/…
用简单的话说,=在指令隔离范围中用于启用双向绑定,@不更新模型,仅更新指令范围值。
@iwein为什么您在jsfiddle.net/maxisam/QrCXh的小提琴代码无法与googleapi -ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js一起使用?仅当我使用您的cdn -code.angularjs.org/1.0.1/angular-1.0.1.js
时,您的代码才有效
我在下面看到了很多不错的答案,但是谁能提供一个指向回答这个问题的官方角度文档的指针?