<!doctype html>
<html ng-app="myApp">
<head>
<script src="http://angularjs-doc.qiniudn.com/angular.min.js"></script>
<script src="http://angularjs-doc.qiniudn.com/angular.js"></script>
</head>
<body>
<div ng-controller ="mainController" >
Outside myDirective: {{ myProperty }}
<div my-directive ng-init="myProperty = 'wow, this is cool'"> <div>
</div>
<script>
angular.module('myApp', [])
.controller("mainController",function (){})
.directive('myDirective', function() {
return {
restrict: 'A',
scope: false,
template:'<div> Inside myDirective: {{ myProperty }} </div>'
};
})
</script> </body>
</html>
<!doctype html>
<html ng-app="myApp">
<head>
<script src="http://angularjs-doc.qiniudn.com/angular.min.js"></script>
<script src="http://angularjs-doc.qiniudn.com/angular.js"></script>
</head>
<body>
<div ng-controller ="mainController" e ng-init="ccc = 'wow, this is cool'">
Outside myDirective: {{ myProperty }}
aaa Outside myDirective: {{ myProperty }}
<div my-directive ng-init="myProperty = 'wow, this is cool'" b-a="ccc" >
</div>
aaa Outside myDirective: {{ myProperty }}
</div>
<script>
angular.module('myApp', [])
.controller("mainController",function (){})
.directive('myDirective', function() {
return {
restrict: 'EA',
//scope: {b:"=bA"},
scope: {},
template:'<div>aaaa Inside myDirective:{{ myProperty }} {{b}}</div>'
};
})
</script> </body>
</html>

http://www.angularjs.cn/A09C

AngularJS.directive系列:嵌套directive的通讯及scope研究

一、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的作用域的更多相关文章

  1. 理解AngularJS的作用域Scope

    AngularJS中,子作用域一般都会通过JavaScript原型继承机制继承其父作用域的属性和方法.但有一个例外:在directive中使用scope: { ... },这种方式创建的作用域是一个独 ...

  2. 理解angularJS中作用域$scope

    angularJS中作用域是什么 作用域(scope)是构成angularJS应用的核心基础,在整个框架中都被广泛使用,因此了解它如何工作是非常重要的 应用的作用域是和应用的数据模型相关联的,同时作用 ...

  3. AngularJS Scope(作用域)

    1. AngularJS Scope(作用域) Scope(作用域) 是应用在 HTML (视图) 和 JavaScript (控制器)之间的纽带. Scope 是一个对象,有可用的方法和属性. Sc ...

  4. 理解AngularJS生命周期:利用ng-repeat动态解析自定义directive

    ng-repeat是AngularJS中一个非常重要和有意思的directive,常见的用法之一是将某种自定义directive和ng-repeat一起使用,循环地来渲染开发者所需要的组件.比如现在有 ...

  5. 转: 理解AngularJS中的依赖注入

    理解AngularJS中的依赖注入 AngularJS中的依赖注入非常的有用,它同时也是我们能够轻松对组件进行测试的关键所在.在本文中我们将会解释AngularJS依赖注入系统是如何运行的. Prov ...

  6. 深入理解AngularJs-scope(一)

    进入正文前的说明:本文中的示例代码并非AngularJs源码,而是来自书籍<<Build Your Own AngularJs>>, 这本书的作者仅依赖jquery和lodas ...

  7. 理解AngularJS中的依赖注入

    点击查看AngularJS系列目录 理解AngularJS中的依赖注入 AngularJS中的依赖注入非常的有用,它同时也是我们能够轻松对组件进行测试的关键所在.在本文中我们将会解释AngularJS ...

  8. AngularJS学习之旅—AngularJS Scope作用域(五)

    1.AngularJS Scope(作用域) Scope(作用域) 是应用在 HTML (视图) 和 JavaScript (控制器)之间的纽带. Scope 是一个对象,有可用的方法和属性. Sco ...

  9. angularJs的作用域和依赖注入

    一.angularJs的作用域 &scope这是局部作用域,先在局部作用域中找,如果没有就在全局作用域中找  &rootScope这是全局作用域 <!DOCTYPE HTML&g ...

随机推荐

  1. 2015.12.29~2015.12.30真题回顾!-- HTML5学堂

    2015.12.29~2015.12.30真题回顾!-- HTML5学堂 吃饭,能够解决饥饿,提供身体运作机能.练习就像吃饭,强壮自己,提升编程技能,寻求编程技巧的最佳捷径!吃饭不能停,练习同样不能停 ...

  2. 【转】linux 编译安装nginx,配置自启动脚本

    linux 编译安装nginx,配置自启动脚本 本文章来给各位同学介绍一篇关于linux 编译安装nginx,配置自启动脚本教程,希望有需要了解的朋友可一起来学习学习哦. 在公司的suse服务器装ng ...

  3. javascript事件类型之界面拖拽交互

    一.在线DEMO 界面拖拽交互

  4. Visual.Studio.2013.IDE+visual.studio.15.preview5 编译器

    硬盘版Visual.Studio.2013.IDE + visual.studio.15.preview5 编译器 使用前注意以下事项: 1.右键-管理员权限安装,VS15补丁.exe,补丁是VS15 ...

  5. Java多线程--wait和join

    首先从公司一道笔试题开始 package test; public class Test implements Runnable { public int i = 0; @Override publi ...

  6. PHP判断访问终端,电脑或手机访问

    函数代码: //判断电脑或手机访问 function is_mobile(){ $user_agent = $_SERVER['HTTP_USER_AGENT']; $mobile_agents = ...

  7. eclipse 工程默认编码修改 JSP编码修改

    1. Window->Preferences->General->Workspace->Text file encoding 将其改为UFT-8  新建的文件即为UTF-8编码 ...

  8. 10G R2 参数文件相关

    CLUSTER_DATABASE Property Description Parameter type Boolean Default value false Modifiable No Range ...

  9. VBA_Excel_教程:分枝循环结构

    Sub 分枝() tmp = Cells(, ).Value '变量不用定义,当前写代码的Sheet Debug.Print tmp " Then Debug.Print "A&q ...

  10. VS2010 项目引用了DLL文件,也写了Using,但是编译时提示:未能找到类型或命名空间名称 <转>

    昨天写了一个很小的winform程序,其中引用了自己写的两个dll文件. 本来认为轻松搞定,结果一编译居然提示:未能找到类型或命名空间名称..... 于是删掉两个dll重新引用,再编译结果依旧!很是郁 ...