一、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. golang mgo的mongo连接池设置:必须手动加上maxPoolSize

    本司礼物系统使用了golang的 mongo库 mgo,中间踩了一些坑,总结下避免大家再踩坑 golang的mgo库说明里是说明了开启连接复用的,但观察实验发现,这并没有根本实现连接的控制,连接复用仅 ...

  2. SSH basics

    SSH, Secure SHell, was designed and created to provide the best security when accessing another comp ...

  3. Socket.IO 1.0 正式发布,快速可靠的实时引擎

    Socket.IO 是目前 Web 领域最火的实时引擎,用于实现基于事件的双向实时的通信.它适用于任何平台,浏览器或设备,专注于可靠性和速度.您可以将数据推送到客户端,并获得实时的计数,日志或图表. ...

  4. UVA 11294 Wedding(2-sat)

    2-sat.不错的一道题,学到了不少. 需要注意这么几点: 1.题目中描述的是有n对夫妇,其中(n-1)对是来为余下的一对办婚礼的,所以新娘只有一位. 2.2-sat问题是根据必然性建边,比如说A与B ...

  5. HDU1160(LIS)

    主题链接:http://acm.hdu.edu.cn/showproblem.php?pid=1160 题意:求体重下降.速度添加的样例最多有多少个 依据体重降序排一下,然后求速度的最长上升子序列 , ...

  6. aProxy: 带认证授权和权限控制的反向代理

    前段时间很多数据库因为没有做好权限控制暴露在外网被删然后遭勒索的事件,而类似的有些内网的web服务也会被开放到公网并且没有做任何权限控制的,这样也会有一定的风险.所以就决定写篇文章简单介绍一个小工具. ...

  7. html5开发学习 html5自学需要怎么学

    记得很多大鳄都说过一句话:只要站在风口上,猪都能飞起来.而对于如今的IT技术领域来说,无疑这只幸运的"猪"非html5莫属.html5开发技术在16年迎来了一个飞跃的发展,这也让很 ...

  8. intellij 快捷键整理

    [常规] Ctrl+Shift + Enter,语句完成 “!”,否定完成,输入表达式时按 “!”键 Ctrl+E,最近的文件 Ctrl+Shift+E,最近更改的文件 Shift+Click,可以关 ...

  9. POJ2356 Find a multiple 抽屉原理(鸽巢原理)

    题意:给你N个数,从中取出任意个数的数 使得他们的和 是 N的倍数: 在鸽巢原理的介绍里面,有例题介绍:设a1,a2,a3,……am是正整数的序列,试证明至少存在正数k和l,1<=k<=l ...

  10. POJ 2373 Dividing the Path (单调队列优化DP)题解

    思路: 设dp[i]为覆盖i所用的最小数量,那么dp[i] = min(dp[k] + 1),其中i - 2b <= k <= i -2a,所以可以手动开一个单调递增的队列,队首元素就是k ...