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学习笔记(十三) js闭包介绍(转)
Jun 20 Javascript
Javascript中的for in循环和hasOwnProperty结合使用
Jun 05 Javascript
Javascript基础知识(三)BOM,DOM总结
Sep 29 Javascript
JavaScript中Number.NEGATIVE_INFINITY值的使用详解
Jun 05 Javascript
Javascript实现图片轮播效果(二)图片序列节点的控制实现
Feb 17 Javascript
原生js实现对Ajax的封装(仿jquery)
Jan 22 Javascript
vue组件中使用iframe元素的示例代码
Dec 13 Javascript
11行JS代码制作二维码生成功能
Mar 09 Javascript
vue中使用heatmapjs的示例代码(结合百度地图)
Sep 05 Javascript
Angular 中使用 FineReport不显示报表直接打印预览
Aug 21 Javascript
JS绘图Flot如何实现动态可刷新曲线图
Oct 16 Javascript
微信小程序实现分页加载效果
Nov 19 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
从零开始学YII2框架(四)扩展插件yii2-kartikgii
2014/08/20 PHP
PHP5.5基于mysqli连接MySQL数据库和读取数据操作实例详解
2019/02/16 PHP
根据分辨率不同,调用不同的css文件
2006/07/07 Javascript
jquery退出each循环的写法
2014/02/26 Javascript
js操作滚动条事件实例
2015/01/29 Javascript
简介AngularJS的视图功能应用
2015/06/17 Javascript
详细解读AngularJS中的表单验证编程
2015/06/19 Javascript
javascript实现的淘宝旅行通用日历组件用法实例
2015/08/03 Javascript
JS实现图片延迟加载并淡入淡出效果的简单方法
2016/08/25 Javascript
几句话带你理解JS中的this、闭包、原型链
2016/09/26 Javascript
jQuery操作json常用方法示例
2017/01/04 Javascript
vue 2.0封装model组件的方法
2017/08/03 Javascript
使用原生js+canvas实现模拟心电图的实例
2017/09/20 Javascript
vue使用vue-i18n实现国际化的实现代码
2018/04/08 Javascript
JavaScript引用类型Function实例详解
2018/08/09 Javascript
原生JS实现的简单小钟表功能示例
2018/08/30 Javascript
Vuex模块化应用实践示例
2020/02/03 Javascript
微信小程序录音实现功能并上传(使用node解析接收)
2020/02/26 Javascript
微信小程序手动添加收货地址省市区联动
2020/05/18 Javascript
vue-cli3配置favicon.ico和title的流程
2020/10/27 Javascript
浅析vue中的nextTick
2020/12/28 Vue.js
Python的Bottle框架中获取制定cookie的教程
2015/04/24 Python
python模拟登录并且保持cookie的方法详解
2017/04/04 Python
Numpy中stack(),hstack(),vstack()函数用法介绍及实例
2018/01/09 Python
在Python 中同一个类两个函数间变量的调用方法
2019/01/31 Python
基于python判断目录或者文件代码实例
2019/11/29 Python
Python 输出详细的异常信息(traceback)方式
2020/04/08 Python
python使用自定义钉钉机器人的示例代码
2020/06/24 Python
python re模块常见用法例举
2021/03/01 Python
英国骑行、跑步、游泳、铁人三项运动装备专卖店:Wiggle
2016/08/23 全球购物
英国度假别墅预订:Sykes Cottages
2017/06/12 全球购物
AURALog面试题软件测试方面
2013/10/22 面试题
大学生职业生涯十年规划书范文
2014/09/17 职场文书
党员自评材料范文
2014/12/17 职场文书
养成教育主题班会
2015/08/13 职场文书
vue中this.$http.post()跨域和请求参数丢失的解决
2022/04/08 Vue.js