开门见山地说,scope:{}使指令与外界隔离开来,使其模板(template)处于non-inheriting(无继承)的状态,当然除非你在其中使用了transclude嵌入,这点之后的笔记会再详细记录的。但是这显然不符合实际开发中的需求,因为实际上,我们经常想要我们的指令能够在特定的情况下与外界进行数据上的交互,这就需要借助绑定策略之手了。

大家知道,当scope选项写为scope:{}这种形式的时候,就已经为指令生成了隔离作用域,现在,我们来看看绑定策略的三种形式:& 、= 、@。

首先是@,它将本地作用域和DOM中的属性值绑定起来(且这个属性的值必须是父级作用域中的),什么意思呢?说的简单一点就是假设你在模板中有个双花括号表达式,然后我们把表达式里的内容和html中指令里特定名字的属性绑定起来,还是不懂?看看下面的代码:

JS代码:

directive("direct",function(){

        return{

            restrict: 'ECMA',

            template: '<div>指令中:{{ name }}</div>',

            scope:{

              name:'@forName'

            }
}
})
.controller("nameController",function($scope){
$scope.Name="张三";
});

HTML代码:

<div ng-controller="nameController">
<direct for-name="{{ Name }}"></direct>
<div>

运行结果可想而知,{{ name }}成功地与父控制器中的Name绑定起来了。当然这里也可以这样写name:'@' 这样写的话,就默认DOM中的属性名为name了意即 for-name="{{ Name }}"可简写为name="{{ Name }}";其实,另外两个符号=和&也有这样的简写规则,方便起见接下来都使用这种写法。
@到此为止,接下来就是'='了。=与@的不同点在于,@是针对字符串(准确来说是表达式expression)而用,但=是针对某个对象的引用;

这么说可能不太专业,但就拿上边的例子而言,我们在html中,把Name这个字符串通过一对双花括号传递给for-name属性,但如果我们用了=,这里传入的Name就不应该是一个字符串,而是一个对象的引用。这不是一个很一目了然的概念,所以我用接下来的两个例子诠释它的含义。

第一个例子:数组中的对象的引用

JS代码:

directive("direct",function(){

        return{

            restrict: 'ECMA',

            template: '<div>指令中:{{ case.name }}</div>',

            scope:{

              case:'='

            }

         } 

  })

.controller("nameController",function($scope){

      $scope.data=[{name:"张三"},{name:"李四"}]; 

});

HTML代码:

<div ng-controller="nameController">

   <direct case="data[0]"></direct>

   <direct case="data[1]"></direct>
<div>

结果就是,一个张三,一个李四。这个例子中,data是一个对象数组,里面包含了两个对象,所以,我们分别把两个对象传递给了case这个属性,case属性就把这个对象的引用传递给了模板中我们写的{{ case.name }}中的case;而如果你在=后边加上了自己定义的名字,那只要把html里case属性换成那个名字就可以了。

第二个例子:经典的双向输入框

按照Angular的入门案例,创建两个双向绑定的输入框,最简单的实现方式就是:

<input ng-model="test"/>
<input ng-model="test"/>

使用ng-model指令就可以做到了。接着,我们在自己的指令中实现这个效果。

JS代码:

directive("direct",function(){

        return{

            restrict: 'ECMA',

            template: '<div>指令中:<input ng-model="model"/></div>',

            scope:{

              model:'='

            }

         } 

  })

.controller("nameController",function($scope){

      $scope.data=[{name:"张三"},{name:"李四"}]; 

});

HTML代码:

<div ng-controller="nameController">

        父级scope中:<input ng-model="mark"/>

        <direct model="mark"/></direct>
</div>

这就完成了,其实只不过是加了一点小把戏,把ng-model换成了model而已。

注意到,这两个例子中,都是使用对象的引用,而不是单纯的字符串,这也是=可以进行双向绑定的关键。

最后是&符号。它的含义是:对父级作用域进行绑定,并将其中的属性包装成一个函数,注意,是属性,意即,任何类型的属性都会被包装成一个函数,比如一个单纯的字符串,或是一个对象数组,或是一个函数方法。

如果是字符串、对象数组和无参的函数,那么可想而知,它们都会被包装成一个无参的函数,若是有参的函数方法则反之,并且我们需要为其传入一个对象。现在,分别针对有参和无参两种情况举例。

无参情况

JS代码:

.directive("direct",function(){

        return{

            restrict: 'ECMA',

            template: '<div>{{ title }}</div>'+'<div><ul><li ng-repeat="x in          contents">{{ x.text }}</li></ul></div>',

            scope:{

              getTitle:'&',
getContent:'&'
},
controller:function($scope){
$scope.title=$scope.getTitle(); //调用无参函数
$scope.contents=$scope.getContent(); //调用无参函数
}
}
}) .controller("nameController",function($scope){ $scope.title="标题"; $scope.contents =[{text:1234},{text:5678}];
});

HTML代码:

<div ng-controller="nameController">
<direct get-title="title" get-content="contents"></direct>
</div>

这个例子有几个注意点:

1.指令的本地属性(即模板里花括号中的属性)需要从本地取值,所以使用了controller选项,而在controller选项中,两个无参方法分别返回了父级scope中的title字符串和contents对象数组。

2.在HTML中,我们把设置了get-title和get-content的属性值为title和contents,这实际上就完成了与父级scope的绑定,因为我们才可以从那儿取得实质的内容。

OK,有参情况

JS代码:

.directive("direct",function(){
return{
restrict: 'ECMA',
template: ' <div><input ng-model="model"/></div> '+' < div><button ng-click="show({name:model})">show</button>',
scope:{
show:'&'
}
}
}) .controller("nameController",function($scope){
$scope.showName=function(name){ alert(name);
}
});

HTML代码:

<div ng-controller="nameController">

      <direct show="showName(name)"></direct> 

  </div>

这个例子中,通过模板中的ng-click触发了show函数并将一个叫做model的对象作为name参数传递了进去,而在html中,我们把show的属性值设为showName(name)。这其中的道理跟无参的例子是大同小异的。

总结:

为什么Angular要为我们提供这样一套绑定策略呢?就是因为它想让我们在为指令创建隔离作用域的同时,还能访问到父级中的属性,这就像,你在隔离作用域身上打了一个洞,然后用一条管道,把指令内部和外界的属性给连起来(绑定),并且一切的通信都只能通过这条管道来实行。这是我目前能做到的最深刻的理解了,可能还有需要的补充和纠正的地方,希望大家能抽空指点我一下,感激不尽!

Angular中directive——scope选项与绑定策略,这个也经常迷惑的。的更多相关文章

  1. AngularJS学习笔记之directive—scope选项与绑定策略

    From:http://www.linuxidc.com/Linux/2015-05/116924.htm scope:{}使指令与外界隔离开来,使其模板(template)处于non-inherit ...

  2. AngularJS学习笔记之directive——scope选项与绑定策略

    开门见山地说,scope:{}使指令与外界隔离开来,使其模板(template)处于non-inheriting(无继承)的状态,当然除非你在其中使用了transclude嵌入,这点之后的笔记会再详细 ...

  3. angular中的 input select 值绑定无效,以及多出一个空白选项问题

    问题: <!-- 问题标签 --> <select ng-model="sortType"> <option value="1"& ...

  4. angular中的scope

    angular.element($0).scope() 什么是scope? scope是一个refer to the application model的object.它是一个expression的执 ...

  5. Angular 中得 scope 作用域梳理

    $scope 的使用贯穿整个 Angular App 应用,它与数据模型相关联,同时也是表达式执行的上下文.有了 $scope 就在视图和控制器之间建立了一个通道,基于作用域视图在修改数据时会立刻更新 ...

  6. angular 中 directive中的多个指令

    <div ng-controller="ctrl1"> <superman weight length speed>superman</superma ...

  7. angular中动态添加的元素绑定事件问题

    $compile http://segmentfault.com/q/1010000000726448/a-1020000000727088 接口下载问题

  8. angular源码分析:angular中$rootscope的实现——scope的一生

    在angular中,$scope是一个关键的服务,可以被注入到controller中,注入其他服务却只能是$rootscope.scope是一个概念,是一个类,而$rootscope和被注入到cont ...

  9. Angular中的数据绑定

    (1)HTML绑定:{{}} (2)属性绑定:[] 注意:属性绑定通常赋值为变量,如果赋值为常量(如字符串常量) 必须用引号括起来,如<img [src]="'../../assets ...

随机推荐

  1. 萌新看过来,你还学不懂VScode插件吗?

    一.前言 VSCode是微软家一个非常轻量化的编辑器,体量虽轻,但是却有异常强大的功能.原因在于VSCode许多强大功能都是基于插件实现的,IDE只提供一个最基本的框架和基本功能,我们需要使用插件来丰 ...

  2. Drools 规则引擎应用 看这一篇就够了

    1 .场景 1.1需求 商城系统消费赠送积分 100元以下, 不加分 100元-500元 加100分 500元-1000元 加500分 1000元 以上 加1000分 ...... 1.2传统做法 1 ...

  3. TTL、RS232、RS485、UART、串口的关系和常见半双工、全双工协议

    串口(UART口).COM口.USB口.DB9.DB25是指的物理接口形式(硬件) TTL.RS-232.RS-485是指的电平标准(电平信号)   我们单片机嵌入式常用的串口有三种(TTL/RS-2 ...

  4. switch语句能否作用在byte上,能否作用在long上,能否作用在String上?

    在Java 7以前,在switch(expr1)中,expr1只能是一个整数表达式(但不包括long和Long)或者枚举常量,整数表达式可以是int基本类型或Integer包装类型,byte.shor ...

  5. Mybatis 动态 sql 有什么用?执行原理?有哪些动态 sql?

    Mybatis 动态 sql 可以在 Xml 映射文件内,以标签的形式编写动态 sql,执行原理 是根据表达式的值 完成逻辑判断并动态拼接 sql 的功能. Mybatis 提供了 9 种动态 sql ...

  6. RabbitMQ 的集群?

    镜像集群模式 你创建的 queue,无论元数据还是 queue 里的消息都会存在于多个实例上,然后 每次你写消息到 queue 的时候,都会自动把消息到多个实例的 queue 里进行消息 同步. 好处 ...

  7. thrift源码分析

    1 前言 学习thrift源码主要为了弄清楚几个问题 thrift客户端和服务端的通信流程是如何的 thrift的IDL中给属性加上编号的作用是什么 thrift中require.optional和默 ...

  8. java-IO异常处理

    以前的异常处理 public class Demo3 { public static void main(String[] args) { //提高fw的作用域 //变量定义的时候可以没有值,但是使用 ...

  9. Linux重启网卡服务Failed to start LSB: Bring up/down networking.

    Linux网卡重启失败,使用 systemctl status network.service命令进行查看状态,发现启动有异常产生 network.service: control process e ...

  10. 转:红黑树和AVL树(平衡二叉树)区别

    本文转载至链接:https://blog.csdn.net/u010899985/article/details/80981053 一.AVL树(平衡二叉树) (1)简介 AVL树是带有平衡条件的二叉 ...