(九)通过几段代码,理清angularJS中的$injector、$rootScope和$scope的概念和关联关系

标签: injectorrootScopescopeangularjs解惑
6522人阅读 评论(4) 收藏 举报
本文章已收录于:
AngularJS知识库
分类:
作者同类文章X

    $injector、$rootScope和$scope是angularJS框架中比较重要的东西,理清它们之间的关系,对我们后续学习和理解angularJS框架都非常有用。

    1、$injector其实是一个IOC容器,包含了很多服务(类似于spring框架中的bean),其它代码能够通过 $injector.get("serviceName")的方式,从injector中获取所需要的服务。详情参考这篇文章

    2、scope是angularJS中的作用域(其实就是存储数据的地方),很类似javascript的原型链。搜索的时候,优先找自己的scope,如果没有找到就沿着作用域链向上搜索,直至到达根作用域rootScope。

    3、$rootScope是由angularJS加载模块的时候自动创建的,每个模块只会有1个rootScope。rootScope创建好会以服务的形式加入到$injector中。也就是说通过$injector.get("$rootScope");能够获取到某个模块的根作用域。更准确的来说,$rootScope是由angularJS的核心模块ng创建的。


    示例1:

    // 新建一个模块
    var module = angular.module("app",[]);
    
    // true说明$rootScope确实以服务的形式包含在模块的injector中
    var hasNgInjector = angular.injector(['app','ng']);  
    console.log("has $rootScope=" + hasNgInjector.has("$rootScope"));//true
    
    // 获取模块相应的injector对象,不获取ng模块中的服务
    // 不依赖于ng模块,无法获取$rootScope服务
    var noNgInjector = angular.injector(['app']);
    console.log("no $rootScope=" + noNgInjector.has("$rootScope"));//false
    
    // 获取angular核心的ng模块
    var ngInjector = angular.injector(['ng']);  
    console.log("ng $rootScope=" + ngInjector.has("$rootScope"));//true
    上面的代码的确可以说明:$rootScope的确是由核心模块ng创建的,并以服务的形式存在于injector中

    如果创建injector的时候,指定了ng模块,那么该injector中就会包含$rootScope服务;否则就不包含$rootScope。


    示例2:

    <!doctype html>
    <html lang="en">
    	<head>
    	   <Meta charset="utf-8">
    	   <script src="angular-1.2.25.js"></script>
    	   <script>
    	  
    		var module = angular.module("app",[]);
    		// 控制器里的$injector,是由angular框架自动创建的
    		function FirstController($scope,$injector,$rootScope)
    		{
    			$rootScope.name="aty";
    		}
    		
    		//自己创建了个injector,依赖于app和ng模块
    		var myInjector = angular.injector(["app","ng"]);
    		var rootScope = myInjector.get("$rootScope");
    		alert(rootScope.name);//udefined
    				
    	   </script> 
    
    	</head>
    	
    	<body ng-app="app">
    		<div id="first" ng-controller="FirstController">
    			<input type="text" ng-model="name">
    			<br>
    			{{name}}
    		</div>	
    	</body>
    	
    </html>

    angular.injector()可以调用多次,每次都返回新建的injector对象。所以我们自己创建的myInjector和angular自动创建的$injector不是同一个对象,那么得到的rootScope也就不是同一个。更详细的可以看另一篇文章中的

    angular.injector()章节。


    示例3:

    <!doctype html>
    <html lang="en">
    	<head>
    	   <script src="angular-1.2.25.js"></script>
    	   <script>
    	  
    		function FirstController($scope,$rootScope)
    		{
    			// true
    			console.log("scope parent :" + ($scope.$parent ==$rootScope));
    		}
    	
    	   </script> 
    	</head>
    	
    	<body ng-app>
    		<div id="first" ng-controller="FirstController">
    			<input type="text" ng-model="name">
    			<br>
    			{{name}}
    		</div>	
    	</body>
    	
    </html>
    ng-controller指令给所在的DOM元素创建了一个新的$scope对象,并作为rootScope的子作用域。$scope是由$rootScope创建的,$scope不会包含在$injector中。

    示例4:

    <!doctype html>
    <html lang="en">
    	<head>
    	   <Meta charset="utf-8">
    	   <title>scope()</title>
    	   <script src="jquery-1.11.1.js"></script>
    	   <script src="angular-1.2.25.js"></script>
    	   
    	   <script>
    	    
    		//记住rootScope,用来判断跨控制器是否相等
    		var first_rootScope = null;
    		//记住scope,用来判断跨控制器是否相等
    		var first_scope = null;
    		//记住injector,用来判断跨控制器是否相等
    		var first_injectot = null;
    		
    		// 第1个angular控制器
    		function FirstController($scope,$rootScope)
    		{
    			$rootScope.name = "aty";
    			first_rootScope = $rootScope;
    			first_injectot = $injector;
    			first_scope = $scope;	
    		
    		}
    		
    		// 第2个angular控制器,主要是来测试跨controller时injector和scope的表现
    		function SecondController($scope,$rootScope)
    		{
    			console.log("first_rootScope==second_rootScope:" + (first_rootScope==$rootScope));//true
    			console.log("first_injectot==second_injector:" + (first_injectot==$injector));//true
    			console.log("first_scope==second_scope:" + (first_scope==$scope));//false
    		}
    	   
    	   </script> 
    
    	</head>
    	
    	<body ng-app>
    		<div id="first" ng-controller="FirstController">
    			<input type="text" ng-model="name">
    			<br>
    			<div id="tips"></div> 
    		</div>
    		
    		<h2>outside of controller</h2>
    		
    		<br>
    		<!--访问每一个应用(模块)的rootScope-->
    		{{$root.name}}
    		<div id="noControllerDiv"/>
    		
    		<div ng-controller="SecondController">
    			
    		</div>
    		
    		
    	</body>
    	
    </html>
    ng-app定义了一个angular模块,每个模块只有一个$rootScope,只有一个$injector,但可以有多个$scope

    弄清了$injector、$rootScope和$scope这3者之间的关系,我们看下angular提供的2个API,一个是scope(),一个是injector()。使用angular.element()返回的DOM对象,都会包含这2个方法,用来获取与之关联的scope和injector。

    由于每个模块的injector是唯一的,所以angular.element().injector()直接返回元素所在模块的injector

    angular.element().scope()可以获取到当前元素的scope或父scope。如果当前元素有scope,则返回自己的scope;如果没有则向父亲方向寻找,如果找不到返回rootScope。即返回作用域链上,距离该元素最近的scope

    <!doctype html>
    <html lang="en">
    	<head>
    	   <Meta charset="utf-8">
    	   <title>scope()</title>
    	   <script src="jquery-1.11.1.js"></script>
    	   <script src="angular-1.2.25.js"></script>
    	   
    	   <script>
    
    		function FirstController($scope,$rootScope)
    		{
    			//获取body对象
    			var domBody = document.getElementsByTagName('body')[0];
    			
    			// 通过ng-app指令所在的DOM元素获取rootScope
    			var rtScope = angular.element(domBody).scope();	
    			
    			//当前元素没有新作用域,获取父作用域即rootScope
    			var noScope = angular.element("#noControllerDiv").scope();	
    			
    			// true
    			console.log("rtScope==noScope:" + (rtScope==noScope));
    			
    			//ng-controller所在的元素,返回的scope
    			var scopeOnController = angular.element("#first").scope();
    			
    			// ng-controller内部的元素返回所在的scope
    			var inController = angular.element("#tips").scope();
    			
    			//true
    			console.log("scopeOnController==inController:" + (scopeOnController==inController));
    			
    			//验证通过DOM获取的scope是否与注入的$scope和$rootScope一致
    			//true
    			console.log("result1:" + (rtScope==$rootScope));
    			//true
    			console.log("result2:" + (inController==$scope));
    
    		}
    	   
    	   </script> 
    
    	</head>
    	
    	<body ng-app>
    		<div id="first" ng-controller="FirstController">
    			<input type="text" ng-model="name">
    			<br>
    			<div id="tips"></div> 
    		</div>
    		
    		<h2>outside of controller</h2>
    		
    		<br>
    		<!--访问每一个应用(模块)的rootScope-->
    		{{$root.name}}
    		<div id="noControllerDiv"/>	
    		
    	</body>
    	
    </html>

    通过几段代码,理清angularJS中的$injector、$rootScope和$scope的概念和关联关系 .的更多相关文章

    1. Swift3.0 中 Strings/Characters 闲聊

      Swift中String类型,说白了就是Character类型实例的集合,在开发过程中,我们一般采用两种方式来求字符串的长度,第一种是转成Objective-C中的Nsstring类型,通过length方法来获取其长度,第二种是通过字符串属性characters.count的方式获得。

    2. Android Studio是否支持用于Android UI设计的AngularJS?

      我对AndroidStudio有疑问:AS在设计XML文件时是否支持AngularJS代码,例如:对于小动画或效果?

    3. android – 如何使用ClientID和ClientSecret在Phonegap中使用Angularjs登录Google OAuth2

      我正尝试使用Angularjs(使用IonicFramework)通过GoogleOAuth2从我的Phonegap应用程序登录.目前我正在使用http://phonegap-tips.com/articles/google-api-oauth-with-phonegaps-inappbrowser.html进行登录.但是当我使用Angular-UI-RouterforIonic时,它正在创建非常

    4. 利用require.js与angular搭建spa应用的方法实例

      这篇文章主要给大家介绍了关于利用require.js与angular搭建spa应用的方法实例,文中通过示例代码给大家介绍的非常详细,对大家的理解和学习具有一定的参考学习价值,需要的朋友们下面跟着小编来一起看看吧。

    5. 详解Angular动态组件

      本文主要介绍了Angular动态组件,对此感兴趣的同学,可以亲自实验一下。

    6. 详解如何使用webpack+es6开发angular1.x

      本篇文章主要介绍了详解如何使用webpack+es6开发angular1.x,具有一定的参考价值,有兴趣的可以了解一下

    7. angular2系列之路由转场动画的示例代码

      本篇文章主要介绍了angular2系列之路由转场动画的示例代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

    8. 一种angular的方法级的缓存注解(装饰器)

      本篇文章主要介绍了一种angular的方法级的缓存注解(装饰器),小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

    9. 动手写一个angular版本的Message组件的方法

      本篇文章主要介绍了动手写一个angular版本的Message组件的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

    10. angular forEach方法遍历源码解读

      这篇文章主要为大家详细了angular forEach方法遍历源码,forEach()方法用于遍历对象或数组,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

    随机推荐

    1. Angular2 innerHtml删除样式

      我正在使用innerHtml并在我的cms中设置html,响应似乎没问题,如果我这样打印:{{poi.content}}它给了我正确的内容:``但是当我使用[innerHtml]=“poi.content”时,它会给我这个html:当我使用[innerHtml]时,有谁知道为什么它会剥离我的样式Angular2清理动态添加的HTML,样式,……

    2. 为Angular根组件/模块指定@Input()参数

      我有3个根组件,由根AppModule引导.你如何为其中一个组件指定@input()参数?也不由AppModalComponent获取:它是未定义的.据我所知,你不能将@input()传递给bootstraped组件.但您可以使用其他方法来做到这一点–将值作为属性传递.index.html:app.component.ts:

    3. angular-ui-bootstrap – 如何为angular ui-bootstrap tabs指令指定href参数

      我正在使用角度ui-bootstrap库,但我不知道如何为每个选项卡指定自定义href.在角度ui-bootstrap文档中,指定了一个可选参数select(),但我不知道如何使用它来自定义每个选项卡的链接另一种重新定义问题的方法是如何使用带有角度ui-bootstrap选项卡的路由我希望现在还不算太晚,但我今天遇到了同样的问题.你可以通过以下方式实现:1)在控制器中定义选项卡href:2)声明一个函数来改变控制器中的散列:3)使用以下标记:我不确定这是否是最好的方法,我很乐意听取别人的意见.

    4. 离子框架 – 标签内部的ng-click不起作用

      >为什么标签标签内的按钮不起作用?>但是标签外的按钮(登陆)工作正常,为什么?>请帮我解决这个问题.我需要在点击时做出回复按钮workingdemo解决方案就是不要为物品使用标签.而只是使用divHTML

    5. Angular 2:将值传递给路由数据解析

      我正在尝试编写一个DataResolver服务,允许Angular2路由器在初始化组件之前预加载数据.解析器需要调用不同的API端点来获取适合于正在加载的路由的数据.我正在构建一个通用解析器,而不是为我的许多组件中的每个组件设置一个解析器.因此,我想在路由定义中传递指向正确端点的自定义输入.例如,考虑以下路线:app.routes.ts在第一个实例中,解析器需要调用/path/to/resourc

    6. angularjs – 解释ngModel管道,解析器,格式化程序,viewChangeListeners和$watchers的顺序

      换句话说:如果在模型更新之前触发了“ng-change”,我可以理解,但是我很难理解在更新模型之后以及在完成填充更改之前触发函数绑定属性.如果您读到这里:祝贺并感谢您的耐心等待!

    7. 角度5模板形式检测形式有效性状态的变化

      为了拥有一个可以监听其包含的表单的有效性状态的变化的组件并执行某些组件的方法,是reactiveforms的方法吗?

    8. Angular 2 CSV文件下载

      我在springboot应用程序中有我的后端,从那里我返回一个.csv文件WheniamhittingtheURLinbrowsercsvfileisgettingdownloaded.现在我试图从我的角度2应用程序中点击此URL,代码是这样的:零件:服务:我正在下载文件,但它像ActuallyitshouldbeBook.csv请指导我缺少的东西.有一种解决方法,但您需要创建一个页面上的元

    9. angularjs – Angular UI-Grid:过滤后如何获取总项数

      提前致谢:)你应该避免使用jQuery并与API进行交互.首先需要在网格创建事件中保存对API的引用.您应该已经知道总行数.您可以使用以下命令获取可见/已过滤行数:要么您可以使用以下命令获取所选行的数量:

    10. angularjs – 迁移gulp进程以包含typescript

      或者我应该使用tsc作为我的主要构建工具,让它解决依赖关系,创建映射文件并制作捆绑包?

    返回
    顶部