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 相关文章推荐
提高 DHTML 页面性能
Dec 25 Javascript
javascript 对象定义方法 简单易学
Mar 22 Javascript
json 入门基础教程 推荐
Oct 31 Javascript
js实现人民币大写金额形式转换
Apr 27 Javascript
关于angularJs指令的Scope(作用域)介绍
Oct 25 Javascript
BootStrap Tooltip插件源码解析
Dec 27 Javascript
jQuery实现获取隐藏div高度的方法示例
Feb 09 Javascript
基于input动态模糊查询的实现方法
Dec 12 Javascript
vue 实现的树形菜的实例代码
Mar 19 Javascript
jQuery实现的鼠标拖动画矩形框示例【可兼容IE8】
May 17 jQuery
vue+element 实现商城主题开发的示例代码
Mar 26 Javascript
ES5新增数组的实现方法
May 12 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
php去除重复字的实现代码
2011/09/16 PHP
初品cakephp 入门基础
2012/02/16 PHP
总结PHP删除字符串最后一个字符的三种方法
2016/08/30 PHP
Smarty模板常见的简单应用分析
2016/11/15 PHP
Paypal实现循环扣款(订阅)功能
2017/03/23 PHP
用js来解决ajax读取页面乱码
2010/11/28 Javascript
关于js获取radio和select的属性并控制的代码
2011/05/12 Javascript
jquery+ajax实现跨域请求的方法
2015/01/20 Javascript
聊一聊JavaScript作用域和作用域链
2016/05/03 Javascript
js控制文本框只能输入中文、英文、数字与指定特殊符号的实现代码
2016/09/09 Javascript
vue通过路由实现页面刷新的方法
2018/01/25 Javascript
浅谈node.js 命令行工具(cli)
2018/05/10 Javascript
详解Ubuntu安装angular-cli遇到的坑
2018/09/08 Javascript
Vue学习之组件用法实例详解
2020/01/06 Javascript
[15:07]lgd_OG_m2_BP
2019/09/10 DOTA
[03:43]TI9战队采访——PSG.LGD
2019/08/22 DOTA
Python中使用wxPython开发的一个简易笔记本程序实例
2015/02/08 Python
python使用pil库实现图片合成实例代码
2018/01/20 Python
Python中的CSV文件使用&quot;with&quot;语句的方式详解
2018/10/16 Python
Python使用requests提交HTTP表单的方法
2018/12/26 Python
TensorFlow基于MNIST数据集实现车牌识别(初步演示版)
2019/08/05 Python
python 实现多维数组(array)排序
2020/02/28 Python
详解Django配置JWT认证方式
2020/05/09 Python
python subprocess pipe 实时输出日志的操作
2020/12/05 Python
Python3中的tuple函数知识点讲解
2021/01/03 Python
浅析Python模块之间的相互引用问题
2021/02/26 Python
Uber Eats台湾:寻找附近提供送餐服务的餐厅
2018/05/07 全球购物
毕业生个人的自我评价优秀范文
2013/10/03 职场文书
初三化学教学反思
2014/01/23 职场文书
《盘古开天地》教学反思
2014/02/28 职场文书
财务部副经理岗位职责范本
2014/06/17 职场文书
五四青年节的活动方案
2014/08/20 职场文书
2014年发展党员工作总结
2014/11/12 职场文书
毕业生爱心捐书倡议书
2015/04/27 职场文书
超搞笑婚前保证书
2015/05/08 职场文书
SpringBoot详解整合Redis缓存方法
2022/07/15 Java/Android