一、directive中的scope

  directive无疑是AngularJS中比较复杂难懂的部分,而directive中个scope更是其中最复杂的部分了,尤其是在嵌套directive中互相通讯的时候。

  单独的directive中,scope概念还是比较简单的,此时scope的三种取值情况为:

  • scope:false  此时,directive没有独立的scope对象,link函数中引用的scope对象来自于当前节点的默认controller
  • scope:true  此时,directive拥有独立的scope对象,此scope是由父scope对象继承而来,可以访问父scope中的所有属性,此时实际上是通过继承链接(prototype链)访问的父scope中的属性,要注意的是,当给此scope继承而来的属性名称赋值的时候,子scope中会相应建立一个本地属性,此时改变的是本scope的变量属性,父scope中的属性是不会改变的。
  • scope:{propertyName:"=@propertyValue"} 此时,directive中拥有一隔离的scope对象,其实就是一个全新的scope对象,和上面取值为true时的区别就是不能访问父scope中的属性,当然还是可以通过$parent属性去访问父scope对象中属性的。

  当情况改变到嵌套directive中的子(或者说内部)directive中时,内部的directive的scope和我们的理解或习惯性的的认知有所不同,而造成这一切的原因是,AngularJS中其实根本没有嵌套directive一说!只要我们脑子里还把内部的directive当成独立的directive来看待就会明白了。比如我们要实现如下的嵌套directive:

<div my-grid height="500" width="300">
<div my-grid-row height="300">
<div my-grid-cell width=".33">
</div>
<div my-grid-cell width=".34">
</div>
<div my-grid-cell width=".33">
</div>
</div>
<div my-grid-row height="200">
<div my-grid-cell width=".5">
</div>
<div my-grid-cell width=".5">
</div>
</div>
</div>
var $myd=angular.module("myDirectives",[]);
$myd.directive("myGrid",function(){
return{
restrict:"A",
scope:{height:"@height",width:"@width"},
link:function(scope,el,attrs){
}
};
});
$myd.directive("myGridRow",function(){
return{
restrict:"A",
scope:true,
link:function(scope,el,attrs){
}
};
});
$myd.directive("myGridCell",function(){
return{
restrict:"A",
scope:true,
link:function(scope,el,attrs){
}
};
});

  开上面代码可知myGrid设置了隔离的scope,myGridRow和myGridCell申请了继承的独立scope,现在猜猜,myGridRow和myGridCell的scope.$parent是谁,是不是myGrid的scope?不知道又没有tx认为(注意下面是示意代码,不是真的如此引用myGridCell和myGridRow的scope)

myGridCell.scope.$parent=myGridRow.scope  

myGridRow.scope.$parent =myGrid.scope

  如果你也和我以前一样这样认为,那么就大错特错了,实际上应该是这样的:

myGridCell.scope.$parent=myGridRow.scope.$parent=myGrid.scope.$parent

  也就是说,这三级的directive的scope的父scope对象是一个人,也就是myGrid所在div元素的父元素或祖先元素节点上指定的ngController或者通过路由设置给出的controller。

  如果myGridRow和myGridCell的scope设为false或是不设置呢,此时myGrid有独立scope而myGridRow和myGridCell都没有,因此分享myGrid父元素的controller的scope,也就是:

myGrid.scope.$parent=myGridRow.scope=myGridCell.scope

  而如果myGridCell和myGridRow的scope也设置为隔离的scope({}),那么此时和第一种情况一样,三个directive的父scope对象也都是同一个对象:myGrid父元素的controller的scope。

二、嵌套directive的通讯

  以上研究了嵌套directive下的scope,可以看到我们不可能通过访问父或子directive中scope方式进行通讯,那么我们究竟应该怎样在各级directive中通讯呢?我知道的有两种方式:

  1,通过注入$rootScope,然后在$rootScope中调用$broadcast和$on,发送和响应事件,这显然不是好的设计。

  2,通过注入父directive的controller。我们看文档知道,directive有一个require属性,这里明确说明require的是指定的directive的controller,此时link函数可以有第四个参数,就是这个controller。下面看示意代码。

var $myd=angular.module("myDirectives",[]);
$myd.directive("myGrid",function(){
return{
restrict:"A",
scope:{height:"@height",width:"@width"},
    controller:function($scope){
        $scope.getHeight=function(){
          return $scope.height;
        };
        $scope.getWidth=function(){
          return $scope.width;
        };
      },
link:function(scope,el,attrs){
       scope.height=parseInt(scope.height);
        $scope.width=parseInt(scope.width);
}
};
});
$myd.directive("myGridRow",function(){
return{
restrict:"A",
scope:true,
     require:"^myGrid",
     controller:function($scope){
        $scope.getWidth=function(){
          return $scope.pCtrl.getWidth();
        }
      },
link:function(scope,el,attrs,pCtrl){
        scope.pCtrl = pCtrl;
        scope.pHeight = pCtrl.getHeight();
        scope.height=parseInt(attrs["height"]);
}
};
});
$myd.directive("myGridCell",function(){
return{
restrict:"A",
scope:true,
     require:"^myGridRow",
link:function(scope,el,attrs,rowCtrl){
        scope.widthRatio = parseFloat(attr["width"]);
        scope.width=scope.widthRatio * rowCtrol.
}
};
});

  由上面代码可见,父子directive通讯需要的两个要素:

  • 父directive中声明controller函数,这和我们平时声明controller差不多,同样可以注入$scope,不同的是这里还可以注入$element,$attrs等,详细的请相关查阅资料。
  • 子directive中添加require属性,内容就是父directive的名字,前面添加"^"是告诉AngularJS到上级的元素中查找父directive的controller,而不是在同元素中找。如果子directive可以脱离父directive单独用,还需要加上"?",以来通知AngularJS,不是必须的,此时link的第四参数有可能为空。

  注意:上述代码只是示意代码,并不能真正工作,如果你使用上述代码将会发现link函数中并不能获取到真正的数值。这是因为例子中嵌套directive是从内到外的顺序来初始化的,子directive的link函数调用时,AngularJS只是初始化了父Directive对象的Controller对象,父directive的link函数并没有调用过,所以你只能取到空值。我的解决方法时子directive在父directive中注册回调函数,然后由父directive在适当的时候回调子directive的方法,或者注册后就由父directive来布局子directive的html元素,具体要看你的目标是什么来定了。

AngularJS.directive系列:嵌套directive的通讯及scope研究的更多相关文章

  1. AngularJS系统学习之Directive(指令)

    本文转自https://www.w3ctech.com/topic/1612 原文作者: Nicolas Bevacqua 原文:AngularJS’ Internals In Depth, Part ...

  2. AngularJS入门心得1——directive和controller如何通信

    粗略地翻了一遍<JavaScript DOM编程艺术>,就以为可以接过AngularJS的一招半式,一个星期过去了,我发现自己还是Too Young,Too Simple!(刚打照面的时候 ...

  3. Angular之指令Directive系列

    项目筹备近期开启Angular学习,指令比较难理解所以记录备案,推荐Angualr实战学习视频大漠穷秋 Angular实战 一.指令directive概述 指令可以对元素绑定事件监听或者改变DOM结构 ...

  4. angularjs可交互的directive

    angularjs可交互的directive http://jsfiddle.net/revolunet/s4gm6/ directive开发上手练手,以注释的方式说明 html <body n ...

  5. AngularJS路由系列(6)-- UI-Router的嵌套State

    本系列探寻AngularJS的路由机制,在WebStorm下开发.本篇主要涉及UI-Route的嵌套State. 假设一个主视图上有两个部分视图,部分视图1和部分视图2,主视图对应着一个state,两 ...

  6. AngularJS创建新指令directive参数说明

    var myapp = angular.module('myapp', []); myapp.directive('worldname', function() { return { template ...

  7. AngularJS路由系列(1)--基本路由配置

    本系列探寻AngularJS的路由机制,在WebStorm下开发.主要包括: ● 路由的Big Picture ● $routeProvider配置路由 ● 使用template属性 ● 使用temp ...

  8. angularjs自动化测试系列之jasmine

    angularjs自动化测试系列之jasmine jasmine参考 html <!DOCTYPE html> <html lang="en"> <h ...

  9. AngularJS路由系列(5)-- UI-Router的路由约束、Resolve属性、路由附加数据、路由进入退出事件

    本系列探寻AngularJS的路由机制,在WebStorm下开发.主要包括: ● UI-Router约束路由参数● UI-Router的Resolve属性● UI-Router给路由附加数据● UI- ...

随机推荐

  1. 遍历目录下的所有文件-os.walk

    #coding:utf-8 import os for root,dirs,files in os.walk("D:"): for fileItem in files: print ...

  2. 基于html5背景图片自适应代码

    基于html5背景图片自适应代码是一款背景不随滚动条滚动,会根据分辨率不同自动匹配对应的背景图片.效果图如下: 在线预览   源码下载 实现的代码. css代码: .jawbone-hero .jaw ...

  3. [转]Handsontable对单元格的操作

    原文地址:http://blog.csdn.net/mafan121/article/details/46119905 1.自动填充单元格数据 fillHandle:true/false    //当 ...

  4. ArrayList, Vector和CopyOnWriteArrayList对比学习

    ArrayList线程不安全的例子 线程安全就是多线程访问时,采用加锁机制,当一个线程访问该类的某个数据时,进行保护,其他线程不能进行访问直到该线程读取完,其他线程才可使用.不会出现数据不一致或者数据 ...

  5. Hadoop与Spark之间的比较

    Hadoop与Spark之间的比较 Hadoop框架的主要模块包括如下: Hadoop Common Hadoop分布式文件系统(HDFS) Hadoop YARN Hadoop MapReduce ...

  6. docker:Error running DeviceCreate (createSnapDevice) dm_task_run failed

    1) service docker stop 2) thin_check /home/docker/devicemapper/devicemapper/metadata 3) thin_check - ...

  7. Sencha Touch 2.3 自定义主题皮肤,颜色

    写博客园越来越懒了,只写重点部分,不明白的可以Q我. 1.当你通过Cmd生成项目之后,App\resources\sass就是我们的样式源文件 2.想自定义自己的样式分为两种方式 扩展:这个是基于st ...

  8. UI设计 - 首页(主页)的任务

    什么是首页 首页,又可以叫主页,是我们的网站或者APP的主要页面,它是我们接触的第一个页面(如果不包含闪屏页和登陆页的话). 特点 首页是一个开始的地方,我们开始真正接触网站提供给我们的内容. 首页是 ...

  9. Docker run 命令的使用方法

    [编者的话]在Docker中,run应该是用户使用最多的命令了,很多读者反馈不是很明白run命令的用法,而且相关的书籍.中文资料中对run命令的描述也不是非常完整,所以DockerOne组织翻译了Do ...

  10. Error:Error converting bytecode to dex: Cause: com.android.dex.DexException: Multiple dex files define Lcom/lidroid/xutils/task/TaskHandler;

    Error:Error converting bytecode to dex: Cause: com.android.dex.DexException: Multiple dex files defi ...