AngularJS指令范围中的'@'和'='有什么区别?

本文翻译自:What is the difference between '@' and '=' in directive scope in AngularJS?

I've read the AngularJS documentation on the topic carefully, and then fiddled around with a directive. 我已经仔细阅读了有关该主题的AngularJS文档,然后摆弄了一条指令。 Here's the fiddle . 这是小提琴

And here are some relevant snippets: 以下是一些相关的摘要:

  • From the HTML: 从HTML:

     <pane bi-title="title" title="{{title}}">{{text}}</pane> 
  • From the pane directive: 从窗格指令:

     scope: { biTitle: '=', title: '@', bar: '=' }, 

There are several things I don't get: 我没有几件事:

  • Why do I have to use "{{title}}" with '@' and "title" with '=' ? 为什么我必须在'@'使用"{{title}}" ,而在'=' "title"使用"title"
  • Can I also access the parent scope directly, without decorating my element with an attribute? 我是否还可以直接访问父范围,而不用属性装饰元素?
  • The documentation says "Often it's desirable to pass data from the isolated scope via an expression and to the parent scope" , but that seems to work fine with bidirectional binding too. 该文档说: “通常希望通过表达式将数据从隔离的范围传递到父范围” ,但这似乎也可以与双向绑定一起使用。 Why would the expression route be better? 为什么表达途径会更好?

I found another fiddle that shows the expression solution too: http://jsfiddle.net/maxisam/QrCXh/ 我发现了另一个也显示表达式解决方案的小提琴: http : //jsfiddle.net/maxisam/QrCXh/


#1楼

参考:https://stackoom.com/question/wx63/AngularJS指令范围中的-和-有什么区别


#2楼

The = means bi-directional binding, so a reference to a variable to the parent scope. =表示双向绑定,因此是对父作用域的变量的引用。 This means, when you change the variable in the directive, it will be changed in the parent scope as well. 这意味着,当您更改指令中的变量时,它也将在父范围中被更改。

@ means the variable will be copied (cloned) into the directive. @表示将变量复制(克隆)到指令中。

As far as I know, <pane bi-title="{{title}}" title="{{title}}">{{text}}</pane> should work too. 据我所知, <pane bi-title="{{title}}" title="{{title}}">{{text}}</pane>应该起作用。 bi-title will receive the parent scope variable value, which can be changed in the directive. bi-title将接收父范围变量值,该值可以在指令中更改。

If you need to change several variables in the parent scope, you could execute a function on the parent scope from within the directive (or pass data via a service). 如果需要在父作用域中更改几个变量,则可以在指令中在父作用域上执行一个函数(或通过服务传递数据)。


#3楼

Why do I have to use "{{title}}" with ' @ ' and "title" with ' = '? 为什么我必须在“ @ ”中使用“ {{title}}”,而在“ = ”中使用“ title”?

@ binds a local/directive scope property to the evaluated value of the DOM attribute . @将本地/定向范围属性绑定到DOM属性评估值 If you use title=title1 or title="title1" , the value of DOM attribute "title" is simply the string title1 . 如果使用title=title1title="title1" ,则DOM属性“ title”的值就是字符串title1 If you use title="{{title}}" , the value of the DOM attribute "title" is the interpolated value of {{title}} , hence the string will be whatever parent scope property "title" is currently set to. 如果您使用title="{{title}}" ,则DOM属性“ title”的值是{{title}}的插值,因此该字符串将是当前设置为父范围的属性“ title”的任何内容。 Since attribute values are always strings, you will always end up with a string value for this property in the directive's scope when using @ . 由于属性值始终是字符串,因此在使用@时,在指令范围内,此属性总是以字符串值结尾。

= binds a local/directive scope property to a parent scope property . =将本地/定向范围属性绑定到父范围属性 So with = , you use the parent model/scope property name as the value of the DOM attribute. 因此,使用= ,您可以将父模型/范围属性名称用作DOM属性的值。 You can't use {{}} s with = . 您不能将{{}}=一起使用

With @, you can do things like title="{{title}} and then some" -- {{title}} is interpolated, then the string "and them some" is concatenated with it. 使用@,您可以执行诸如title="{{title}} and then some"内插title="{{title}} and then some" -{{title}},然后将字符串“ and them some some”与之串联。 The final concatenated string is what the local/directive scope property gets. 最终的串联字符串是local / directive范围属性所获得的。 (You can't do this with = , only @ .) (您不能使用= ,只能使用@ 。)

With @ , you will need to use attr.$observe('title', function(value) { ... }) if you need to use the value in your link(ing) function. 使用@时 ,如果需要在链接函数中使用值,则需要使用attr.$observe('title', function(value) { ... }) Eg, if(scope.title == "...") won't work like you expect. 例如, if(scope.title == "...")将无法正常工作。 Note that this means you can only access this attribute asynchronously . 请注意,这意味着您只能异步访问此属性。 You don't need to use $observe() if you are only using the value in a template. 如果仅在模板中使用值,则无需使用$ observe()。 Eg, template: '<div>{{title}}</div>' . 例如, template: '<div>{{title}}</div>'

With = , you don't need to use $observe. 使用= ,您不需要使用$ observe。

Can I also access the parent scope directly, without decorating my element with an attribute? 我是否还可以直接访问父范围,而不用属性装饰元素?

Yes, but only if you don't use an isolate scope. 是的,但前提是您不使用隔离范围。 Remove this line from your directive 从指令中删除此行

scope: { ... }

and then your directive will not create a new scope. 然后您的指令将不会创建新的作用域。 It will use the parent scope. 它将使用父范围。 You can then access all of the parent scope properties directly. 然后,您可以直接访问所有父范围属性。

The documentation says "Often it's desirable to pass data from the isolated scope via an expression and to the parent scope", but that seems to work fine with bidirectional binding too. 该文档说:“通常希望通过表达式将数据从隔离范围传递到父范围”,但这似乎也可以与双向绑定一起使用。 Why would the expression route be better? 为什么表达途径会更好?

Yes, bidirectional binding allows the local/directive scope and the parent scope to share data. 是的,双向绑定允许本地/指令范围和父范围共享数据。 "Expression binding" allows the directive to call an expression (or function) defined by a DOM attribute -- and you can also pass data as arguments to the expression or function. “表达式绑定”允许指令调用由DOM属性定义的表达式(或函数)-您还可以将数据作为参数传递给表达式或函数。 So, if you don't need to share data with the parent -- you just want to call a function defined in the parent scope -- you can use the & syntax. 因此,如果您不需要与父级共享数据(您只想调用父级作用域中定义的函数),则可以使用语法。

See also 也可以看看


#4楼

Even when the scope is local, as in your example, you may access the parent scope through the property $parent . 即使在作用域是本地作用域(如您的示例)中,也可以通过属性$parent访问父作用域。 Assume in the code below, that title is defined on the parent scope. 假定在下面的代码中,该title是在父作用域上定义的。 You may then access title as $parent.title : 然后,您可以将title作为$parent.title访问:

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

However in most cases the same effect is better obtained using attributes. 但是,在大多数情况下,使用属性可以更好地获得相同的效果。

An example of where I found the "&" notation, which is used "to pass data from the isolated scope via an expression and to the parent scope", useful (and a two-way databinding could not be used) was in a directive for rendering a special datastructure inside an ng-repeat. 我在指令中找到了一个示例,其中“&”符号用于“将数据从隔离范围通过表达式传递到父范围”,这很有用(并且无法使用双向数据绑定)用于在ng-repeat中呈现特殊的数据结构。

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

One part of the rendering was a delete button and here it was useful to attach a deletefunction from the outside scope via &. 渲染的一部分是删除按钮,这里通过&从外部作用域附加delete函数很有用。 Inside the render-directive it looks like 在渲染指令中,它看起来像

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

2-way databinding ie data = "=" can not be used as the delete function would run on every $digest cycle, which is not good, as the record is then immediately deleted and never rendered. 2路数据绑定,即data = "="不能被使用,因为删除功能将在每个$digest循环上运行,这是不好的,因为该记录会立即被删除并且从不呈现。


#5楼

If you would like to see more how this work with a live example. 如果您想通过实际示例了解更多信息。 http://jsfiddle.net/juanmendez/k6chmnch/ 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>"
    };
});

#6楼

There are a lot of great answers here, but I would like to offer my perspective on the differences between @ , = , and & binding that proved useful for me. 这里有很多不错的答案,但是我想对@=&绑定之间的差异提供我的观点,这对我来说很有用。

All three bindings are ways of passing data from your parent scope to your directive's isolated scope through the element's attributes: 这三种绑定都是通过元素的属性将数据从父范围传递到指令的隔离范围的方法:

  1. @ binding is for passing strings. @绑定用于传递字符串。 These strings support {{}} expressions for interpolated values. 这些字符串支持内插值的{{}}表达式。 For example: . 例如: 。 The interpolated expression is evaluated against directive's parent scope. 根据指令的父范围对插值表达式进行求值。

  2. = binding is for two-way model binding. =绑定用于双向模型绑定。 The model in parent scope is linked to the model in the directive's isolated scope. 父范围中的模型链接到指令隔离范围中的模型。 Changes to one model affects the other, and vice versa. 对一个模型的更改会影响另一个模型,反之亦然。

  3. & binding is for passing a method into your directive's scope so that it can be called within your directive. 绑定用于将方法传递到指令的作用域中,以便可以在指令中调用它。 The method is pre-bound to the directive's parent scope, and supports arguments. 该方法预先绑定到指令的父范围,并支持参数。 For example if the method is hello(name) in parent scope, then in order to execute the method from inside your directive, you must call $scope.hello({name:'world'}) 例如,如果方法在父范围内是hello(name),则为了从指令内部执行该方法,必须调用$ scope.hello({name:'world'})

I find that it's easier to remember these differences by referring to the scope bindings by a shorter description: 我发现通过用简短的描述引用作用域绑定更容易记住这些差异:

  • @ Attribute string binding @ 属性字符串绑定
  • = Two-way model binding = 双向模型绑定
  • & Callback method binding & 回调方法绑定

The symbols also make it clearer as to what the scope variable represents inside of your directive's implementation: 这些符号还使范围变量在指令的实现内部表示什么变得更加清晰:

  • @ string @ 字符串
  • = model = 模型
  • & method & 方法

In order of usefulness (for me anyways): 为了有用(无论如何对我来说):

  1. = =
  2. @ @
  3. &
发布了0 篇原创文章 · 获赞 3 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/p15097962069/article/details/105296892