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 相关文章推荐
使用jquery mobile做幻灯播放效果实现步骤
Jan 04 Javascript
js实现延迟加载的方法
Jun 24 Javascript
jQuery中队列queue()函数的实例教程
May 03 Javascript
分享jQuery网页元素拖拽插件
Dec 01 Javascript
HTML5 实现的一个俄罗斯方块实例代码
Sep 19 Javascript
详解webpack+gulp实现自动构建部署
Jun 29 Javascript
浅谈vuex之mutation和action的基本使用
Aug 29 Javascript
vue 里面使用axios 和封装的示例代码
Sep 01 Javascript
localstorage实现带过期时间的缓存功能
Jun 28 Javascript
js实现随机点名器精简版
Jun 29 Javascript
vue等两个接口都返回结果再执行下一步的实例
Sep 08 Javascript
浅谈Vue使用Cascader级联选择器数据回显中的坑
Oct 31 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
屏蔽机器人从你的网站搜取email地址的php代码
2012/11/14 PHP
php取得字符串首字母的方法
2015/03/25 PHP
php求数组全排列,元素所有组合的方法
2016/05/05 PHP
如何用PHP做到页面注册审核
2017/03/02 PHP
php实现的双色球算法示例
2017/06/20 PHP
PHP中使用CURL发送get/post请求上传图片批处理功能
2018/10/15 PHP
Javascript 更新 JavaScript 数组的 uniq 方法
2008/01/23 Javascript
jQuery右键菜单contextMenu使用实例
2011/09/28 Javascript
cookie.js 加载顺序问题怎么才有效
2013/07/31 Javascript
通过$(this)使用jQuery包装后的方法或属性
2014/05/18 Javascript
javascript验证身份证号
2015/03/03 Javascript
jquery实现简洁文件上传表单样式
2015/11/02 Javascript
javascript实现别踩白块儿小游戏程序
2015/11/22 Javascript
Bootstrap中文本框的宽度变窄并且加入一副验证码图片的实现方法
2016/06/23 Javascript
IE8利用自带的setCapture和releaseCapture解决iframe的拖拽事件方法
2016/10/25 Javascript
微信小程序微信支付接入开发实例详解
2017/04/12 Javascript
jQueryeasyui 中如何使用datetimebox 取两个日期间相隔的天数
2017/06/13 jQuery
微信小程序实现验证码获取倒计时效果
2018/02/08 Javascript
element ui table(表格)实现点击一行展开功能
2018/12/04 Javascript
Vue form表单动态添加组件实战案例
2019/09/02 Javascript
[05:39]2014DOTA2国际邀请赛 DK晋级胜者组专访战队国士无双
2014/07/14 DOTA
python实现监控linux性能及进程消耗性能的方法
2014/07/25 Python
python使用线程封装的一个简单定时器类实例
2015/05/16 Python
python fabric实现远程部署
2017/01/05 Python
使用pandas将numpy中的数组数据保存到csv文件的方法
2018/06/14 Python
python二进制读写及特殊码同步实现详解
2019/10/11 Python
基于python2.7实现图形密码生成器的实例代码
2019/11/05 Python
Python字符编码转码之GBK,UTF8互转
2020/02/09 Python
世界顶级俱乐部的官方球衣和套装:Subside Sports
2018/04/22 全球购物
Under Armour安德玛英国官网:美国高端运动科技品牌
2018/09/17 全球购物
校园会短篇的广播稿
2014/10/21 职场文书
2015社区个人工作总结范文
2015/05/13 职场文书
HTML基本元素标签介绍
2022/02/28 HTML / CSS
2021年国漫热度排行前十,完美世界上榜,第四是美国动画作品
2022/03/18 国漫
golang的文件创建及读写操作
2022/04/14 Golang
Windows server 2012 配置Telnet以及用法详解
2022/04/28 Servers