AngularJS中$injector、$rootScope和$scope的概念和关联关系深入分析


Posted in Javascript onJanuary 19, 2017

本文实例讲述了AngularJS中$injector、$rootScope和$scope的概念和关联关系。分享给大家供大家参考,具体如下:

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

1、$injector其实是一个IOC容器,包含了很多服务(类似于spring框架中的bean),其它代码能够通过       $injector.get("serviceName")的方式,从injector中获取所需要的服务。详情参考这篇文章:《AngularJS的依赖注入实例分析(使用module和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也就不是同一个。更详细的可以看另一篇文章《AngularJS的依赖注入实例分析(使用module和injector)》中的angular.injector()相关章节。

示例3:

<!doctype html>
<html lang="en">
  <head>
    <script src="angular-1.2.25.js"></script>
    <script>
    function FirstController($scope,$injector,$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,$injector,$rootScope)
    {
      $rootScope.name = "aty";
      first_rootScope = $rootScope;
      first_injectot = $injector;
      first_scope = $scope;
    }
    // 第2个angular控制器,主要是来测试跨controller时injector和scope的表现
    function SecondController($scope,$injector,$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,$injector,$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程序设计有所帮助。

Javascript 相关文章推荐
javascript引导程序
Oct 26 Javascript
JavaScript Event学习第二章 Event浏览器兼容性
Feb 07 Javascript
jQuery+html5实现div弹出层并遮罩背景
Apr 15 Javascript
jQuery中的AjaxSubmit使用讲解
Sep 25 Javascript
Angular2从搭建环境到开发步骤详解
Oct 17 Javascript
JavaScript中object和Object的区别(详解)
Feb 27 Javascript
AngularJS获取json数据的方法详解
May 27 Javascript
浅谈Vue Element中Select下拉框选取值的问题
Mar 01 Javascript
使用vue完成微信公众号网页小记(推荐)
Apr 28 Javascript
微信公众号获取用户地理位置并列出附近的门店的示例代码
Jul 25 Javascript
JavaScript switch语句使用方法简介
Dec 30 Javascript
手机浏览器唤起微信分享(JS)
Oct 11 Javascript
bootstrap组件之导航组件使用方法
Jan 19 #Javascript
bootstrap输入框组件使用方法详解
Jan 19 #Javascript
bootstrap组件之按钮式下拉菜单小结
Jan 19 #Javascript
AngularJS框架中的双向数据绑定机制详解【减少需要重复的开发代码量】
Jan 19 #Javascript
AngularJs中 ng-repeat指令中实现含有自定义指令的动态html的方法
Jan 19 #Javascript
AngularJS的依赖注入实例分析(使用module和injector)
Jan 19 #Javascript
学好js,这些js函数概念一定要知道【推荐】
Jan 19 #Javascript
You might like
Terran热键控制
2020/03/14 星际争霸
yii2 RBAC使用DbManager实现后台权限判断的方法
2016/07/23 PHP
PHP工厂模式、单例模式与注册树模式实例详解
2019/06/03 PHP
MacOS下PHP7.1升级到PHP7.4.15的方法
2021/02/22 PHP
jQuery的12招常用技巧分享
2011/08/08 Javascript
js实现div闪烁原理及实现代码
2014/06/24 Javascript
jquery用ajax方式从后台获取json数据后如何将内容填充到下拉列表
2015/08/26 Javascript
浅谈JavaScript 中有关时间对象的方法
2016/08/15 Javascript
JS中substring与substr的用法
2016/11/16 Javascript
详解vue与后端数据交互(ajax):vue-resource
2017/03/16 Javascript
React中上传图片到七牛的示例代码
2017/10/10 Javascript
Vue中使用vee-validate表单验证的方法
2018/05/09 Javascript
详解puppeteer使用代理
2018/12/27 Javascript
详解Angular Karma测试的持续集成实践
2019/11/15 Javascript
原生js实现日期选择插件
2020/05/21 Javascript
详解vue之自行实现派发与广播(dispatch与broadcast)
2021/01/19 Vue.js
[01:53]DOTA2超级联赛专访Zhou 五年职业青春成长
2013/05/29 DOTA
python进程类subprocess的一些操作方法例子
2014/11/22 Python
python实现图片处理和特征提取详解
2017/11/13 Python
浅谈python中np.array的shape( ,)与( ,1)的区别
2018/06/04 Python
python 对dataframe下面的值进行大规模赋值方法
2018/06/09 Python
python爬虫框架scrapy实现模拟登录操作示例
2018/08/02 Python
python矩阵的转置和逆转实例
2018/12/12 Python
在Python中通过getattr获取对象引用的方法
2019/01/21 Python
Python不同目录间进行模块调用的实现方法
2019/01/29 Python
Python字符串逆序的实现方法【一题多解】
2019/02/18 Python
Python如何将图像音视频等资源文件隐藏在代码中(小技巧)
2020/02/16 Python
PyTorch中Tensor的数据统计示例
2020/02/17 Python
各大浏览器 CSS3 和 HTML5 兼容速查表 图文
2010/04/01 HTML / CSS
HTML5 Canvas实现烟花绽放特效
2016/03/02 HTML / CSS
欧洲顶级的童装奢侈品购物网站:Bambini Fashion(面向全球)
2018/04/24 全球购物
英国顶级水晶珠宝零售商之一:Tresor Paris
2019/04/27 全球购物
存储过程的优缺点是什么
2015/01/10 面试题
2015年世界水日活动总结
2015/02/09 职场文书
因个人工作失误检讨书
2019/06/21 职场文书
详细总结Python常见的安全问题
2021/05/21 Python