Angular Module声明和获取重载实例代码


Posted in Javascript onSeptember 14, 2016

module是angular中重要的模块组织方式,它提供了将一组内聚的业务组件(controller、service、filter、directive…)封装在一起的能力。这样做可以将代码按照业务领域问题分module的封装,然后利用module的依赖注入其关联的模块内容,使得我们能够更好的”分离关注点“,达到更好的”高内聚低耦合“。”高内聚低耦合“是来自面向对象设计原则。内聚是指模块或者对象内部的完整性,一组紧密联系的逻辑应该被封装在同一模块、对象等代码单元中,而不是分散在各处;耦合则指模块、对象等代码单元之间的依赖程度,如果一个模块的修改,会影响到另一个模块,则说明这两模块之间是相互依赖紧耦合的。

同时module也是我们angular代码的入口,首先需要声明module,然后才能定义angular中的其他组件元素,如controller、service、filter、directive、config代码块、run代码块等。

关于module的定义为:angular.module(‘com.ngbook.demo', [])。关于module函数可以传递3个参数,它们分别为:

  1. name:模块定义的名称,它应该是一个唯一的必选参数,它会在后边被其他模块注入或者是在ngAPP指令中声明应用程序主模块;
  2. requires:模块的依赖,它是声明本模块需要依赖的其他模块的参数。特别注意:如果在这里没有声明模块的依赖,则我们是无法在模块中使用依赖模块的任何组件的;它是个可选参数。
  3. configFn: 模块的启动配置函数,在angular config阶段会调用该函数,对模块中的组件进行实例化对象实例之前的特定配置,如我们常见的对$routeProvider配置应用程序的路由信息。它等同于”module.config“函数,建议用”module.config“函数替换它。这也是个可选参数。

对于angular.module方法,我们常用的方式有有种,分别为angular.module(‘com.ngbook.demo', [可选依赖])和angular.module(‘com.ngbook.demo')。请注意它是完全不同的方式,一个是声明创建module,而另外一个则是获取已经声明了的module。在应用程序中,对module的声明应该有且只有一次;对于获取module,则可以有多次。推荐将angular组件独立分离在不同的文件中,module文件中声明module,其他组件则引入module,需要注意的是在打包或者script方式引入的时候,我们需要首先加载module声明文件,然后才能加载其他组件模块。

在angular中文社区群中,有时会听见某些同学问关于”ng:areq“的错误:

 [ng:areq] Argument 'DemoCtrl' is not a function, got undefined!

这往往是因为忘记定义controller或者是声明了多次module,多次声明module会导致前边的module定义信息被清空,所以程序就会找不到已定义的组件。这我们也能从angular源码中了解到(来自loader.js):

function setupModuleLoader(window) {
      ...
      function ensure(obj, name, factory) {
        return obj[name] || (obj[name] = factory());
      }
      var angular = ensure(window, 'angular', Object);
      return ensure(angular, 'module', function() {
        var modules = {};
        return function module(name, requires, configFn) {
          var assertNotHasOwnProperty = function(name, context) {
            if (name === 'hasOwnProperty') {
              throw ngMinErr('badname', 'hasOwnProperty is not a valid {0} name', context);
            }
          };

          assertNotHasOwnProperty(name, 'module');
          if (requires && modules.hasOwnProperty(name)) {
            modules[name] = null;
          }
          return ensure(modules, name, function() {
            if (!requires) {
              throw $injectorMinErr('nomod', "Module '{0}' is not available! You either misspelled " +
                "the module name or forgot to load it. If registering a module ensure that you " +
                "specify the dependencies as the second argument.", name);
            }
            var invokeQueue = [];
            var runBlocks = [];
            var config = invokeLater('$injector', 'invoke');
            var moduleInstance = {
              _invokeQueue: invokeQueue,
              _runBlocks: runBlocks,
              requires: requires,
              name: name,
              provider: invokeLater('$provide', 'provider'),
              factory: invokeLater('$provide', 'factory'),
              service: invokeLater('$provide', 'service'),
              value: invokeLater('$provide', 'value'),
              constant: invokeLater('$provide', 'constant', 'unshift'),
              animation: invokeLater('$animateProvider', 'register'),
              filter: invokeLater('$filterProvider', 'register'),
              controller: invokeLater('$controllerProvider', 'register'),
              directive: invokeLater('$compileProvider', 'directive'),
              config: config,
              run: function(block) {
                runBlocks.push(block);
                return this;
              }
            };
            if (configFn) {
              config(configFn);
            }
            return moduleInstance;

            function invokeLater(provider, method, insertMethod) {
              return function() {
                invokeQueue[insertMethod || 'push']([provider, method, arguments]);
                return moduleInstance;
              };
            }
          });
        };
      });
    }

在代码中,我们能了解到angular在启动时,会设置全局的angular对象,然后在angular对象上发布module这个API。关于module API代码,能清晰的看见第一行谓语句,module名称不能以hasOwnProperty命名,否则会抛出”badname“的错误信息。紧接着,如果传入了name参数,其表示是声明module,则会删除已有的module信息,将其置为null。

从moduleInstance的定义,我们能够看出,angular.module为我们公开的API有:invokeQueue、runBlocks、requires、name、provider、factory、servic、value、constant、animation、filter、controller、directive、config、run。其中invokeQueue和runBlocks是按名约定的私有属性,请不要随意使用,其他API都是我们常用的angular组件定义方法,从invokeLater代码中能看到这类angular组件定义的返回依然是moduleInstance实例,这就形成了流畅API,推荐使用链式定义这些组件,而不是声明一个全局的module变量。

最后,如果传入了第三个参数configFn,则会将它配置到config信息中,当angular进入config阶段时,它们将会依次执行,进行对angular应用或者angular组件如service等的实例化前的配置。

以上就是对Angular Module声明和获取重载的资料整理,后续继续补充相关资料,谢谢大家对本站的支持!

Javascript 相关文章推荐
aspx中利用js实现确认删除代码
Jul 22 Javascript
ExtJs中gridpanel分组后组名排序实例代码
Dec 02 Javascript
js实现简单的手风琴效果
Feb 27 Javascript
JS实现浏览器打印、打印预览示例
Feb 28 Javascript
JS实现的文字间歇循环滚动效果完整示例
Feb 13 Javascript
更改BootStrap popover的默认样式及popover简单用法
Sep 13 Javascript
在vue项目中优雅的使用SVG的方法实例详解
Dec 03 Javascript
mongodb初始化并使用node.js实现mongodb操作封装方法
Apr 02 Javascript
微信小程序实现bindtap等事件传参
Apr 08 Javascript
JS+canvas五子棋人机对战实现步骤详解
Jun 04 Javascript
Ant Design Pro 之 ProTable使用操作
Oct 31 Javascript
vue-amap根据地址回显地图并mark的操作
Nov 03 Javascript
javascript经典特效分享 手风琴、轮播图、图片滑动
Sep 14 #Javascript
Angular 应用技巧总结
Sep 14 #Javascript
AngularJS 所有版本下载地址
Sep 14 #Javascript
JS组件系列之使用HTML标签的data属性初始化JS组件
Sep 14 #Javascript
Angularjs 制作购物车功能实例代码
Sep 14 #Javascript
一步一步封装自己的HtmlHelper组件BootstrapHelper(三)
Sep 14 #Javascript
Angular ng-repeat 对象和数组遍历实例
Sep 14 #Javascript
You might like
PHP面向对象三大特点学习(充分理解抽象、封装、继承、多态)
2012/05/07 PHP
PHP面向对象学习笔记之二 生成对象的设计模式
2012/10/06 PHP
二进制交叉权限微型php类分享
2014/02/07 PHP
PHP动态输出JavaScript代码实例
2015/02/12 PHP
基于Laravel实现的用户动态模块开发
2017/09/21 PHP
PhpStorm 如何优雅的调试Hyperf的方法步骤
2019/11/24 PHP
JavaScript的Module模式编程深入分析
2013/08/13 Javascript
使用控制台破解百小度一个月只准改一次名字
2015/08/13 Javascript
AngularJS 表达式详细讲解及实例代码
2016/07/26 Javascript
利用JS判断字符串是否含有数字与特殊字符的方法小结
2016/11/25 Javascript
微信小程序 PHP后端form表单提交实例详解
2017/01/12 Javascript
基于Bootstrap的标签页组件及bootstrap-tab使用说明
2017/07/25 Javascript
webpack实现热更新(实施同步刷新)
2017/07/28 Javascript
angular 实现的输入框数字千分位及保留几位小数点功能示例
2018/06/19 Javascript
vue中Element-ui 输入银行账号每四位加一个空格的实现代码
2018/09/14 Javascript
基于vue中keep-alive缓存问题的解决方法
2018/09/21 Javascript
layui之table checkbox初始化时选中对应选项的方法
2019/09/02 Javascript
[01:07:41]IG vs VGJ.T 2018国际邀请赛小组赛BO2 第一场 8.18
2018/08/19 DOTA
[46:28]EG vs Liquid 2019国际邀请赛淘汰赛 败者组 BO3 第二场 8.23
2019/09/05 DOTA
学习python之编写简单简单连接数据库并执行查询操作
2016/02/27 Python
Python找出最小的K个数实例代码
2018/01/04 Python
Flask框架各种常见装饰器示例
2018/07/17 Python
小白入门篇使用Python搭建点击率预估模型
2018/10/12 Python
Python读取txt某几列绘图的方法
2018/10/14 Python
使用Python轻松完成垃圾分类(基于图像识别)
2019/07/09 Python
django中media媒体路径设置的步骤
2019/11/15 Python
django框架中间件原理与用法详解
2019/12/10 Python
使用 Python 遍历目录树的方法
2020/02/29 Python
美国家居装饰和豪华家具购物网站:One Kings Lane
2018/12/24 全球购物
芬兰设计商店美国:Finnish Design Shop US
2019/03/25 全球购物
武汉瑞得软件笔试题
2015/10/27 面试题
军校本科大学生自我评价
2014/01/14 职场文书
美术学专业求职信
2014/07/23 职场文书
SpringBoot整合MongoDB的实现步骤
2021/06/23 MongoDB
Python 数据可视化神器Pyecharts绘制图像练习
2022/02/28 Python
springboot+zookeeper实现分布式锁
2022/03/21 Java/Android