AngularJS深入(2)——模块化

setupModuleLoader

该方法主要用于设置模块加载器,源码比较长,并且使用了多层闭包。首先在该方法中,定义了一个非常有用的方法ensure,代码如下:

function ensure(obj, name, factory) {
return obj[name] || (obj[name] = factory());
}

很容易理解,当objname属性的时候,作为getter来使用,否则作为setter来使用。

然后可以将setupModuleLoader简化如下:

function setupModuleLoader(window) {
// ... ...
return angular.module = (function() {
var modules = {};
return function module(name, requires, configFn) {
return ensure(modules, name, function() {
// ... ...
var moduleInstance = {
// ... ...
};
return moduleInstance;
});
}
})();
}

但是这样依然不够直观清晰,接下来打破闭包,将代码继续简化调整如下:

function setupModuleLoader(window) {
var modules = {};

angular.module = function module(name, requires, configFn) {
if (modules[name]) {
return modules[name];
}

var moduleInstance = {
// ... ...
};
modules.name = moduleInstance;
return moduleInstance;
};

return module;
}

到这里可以发现,该方法主要是为angular对象定义了module方法。接下来主要对angular.module方法进行分析。源码结构如下:

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() {
// ... ...
});
}

首先是确保模块名不为hasOwnProperty,这是因为在接下来的判断语句中会调用modules.hasOwnProperty,如果模块名也为hasOwnProperty,就会出问题。接下来是一个判断,如果requires存在且modules已经有相应的模块,则重置其为null,这里也就是对同名模块的重新注册。

这里可以看到,如果通过angular.module(name)来调用,则会直接跳过判断语句,进入ensure,此时如果存在该模块,则直接返回modules[name],在这种情况下,angular.module的作用相当于是一个getter。如果通过angular.module(name, requires[, configFn])来调用,则用作setter,来注册一个模块。

模块注册的代码如下:

function() {
    var invokeQueue = [];
    var configBlocks = [];
    var runBlocks = [];
    var config = invokeLater(‘$injector‘, ‘invoke‘, ‘push‘, configBlocks);

    var moduleInstance = {
        _invokeQueue: invokeQueue,
        _configBlocks: configBlocks,
        _runBlocks: runBlocks,
        requires: requires,
        name: name,
        provider: invokeLaterAndSetModuleName(‘$provide‘, ‘provider‘),
        factory: invokeLaterAndSetModuleName(‘$provide‘, ‘factory‘),
        service: invokeLaterAndSetModuleName(‘$provide‘, ‘service‘),
        value: invokeLater(‘$provide‘, ‘value‘),
        constant: invokeLater(‘$provide‘, ‘constant‘, ‘unshift‘),
        decorator: invokeLaterAndSetModuleName(‘$provide‘, ‘decorator‘),
        animation: invokeLaterAndSetModuleName(‘$animateProvider‘, ‘register‘),
        filter: invokeLaterAndSetModuleName(‘$filterProvider‘, ‘register‘),
        controller: invokeLaterAndSetModuleName(‘$controllerProvider‘, ‘register‘),
        directive: invokeLaterAndSetModuleName(‘$compileProvider‘, ‘directive‘),
        config: config,
        run: function(block) {
            runBlocks.push(block);
            return this;
        }
    };

    if (configFn) {
        config(configFn);
    }

    return moduleInstance;

    function invokeLater(provider, method, insertMethod, queue) {
        if (!queue) queue = invokeQueue;
        return function() {
            queue[insertMethod || ‘push‘]([provider, method, arguments]);
            return moduleInstance;
        };
    }

    function invokeLaterAndSetModuleName(provider, method) {
        return function(recipeName, factoryFunction) {
            if (factoryFunction && isFunction(factoryFunction)) factoryFunction.$$moduleName = name;
            invokeQueue.push([provider, method, arguments]);
            return moduleInstance;
        };
    }

}

这里主要看下invokeLaterinvokeLaterAndSetModuleName这两个内部方法。invokeLater接收四个参数,第四个参数默认为invokeQueue这个数组,它返回一个函数,该函数的作用就是将数组[provider, method, arguments]添加到第四个参数指明的数组中。invokeLaterAndSetModuleName方法与此类似,只不过多了一个设置函数的$$moduleName的操作。

看一个简单的例子:

var moduleA = angular.module(‘ModuleA‘, []),
    moduleB = angular.module(‘ModuleB‘, []),
    moduleC = angular.module(‘ModuleC‘, [‘ModuleA‘, ‘ModuleB‘]);
moduleC.config(function myConfig() {})
    .controller(‘TestCtrl‘, [‘$scope‘, function($scope) {}]);
console.dir(moduleC);

下面是截取的部分查看结果:

// moduleC._configBlocks
[
    [‘$injector‘, ‘invoke‘, [function myConfig(){}]]
]

// moduleC._invokeQueue
[
    [‘$controllerProvider‘, ‘register‘,
        [‘TestCtrl‘, [‘$scope‘, function test($scope){}]]
    ]
]

// moduleC.requires
[‘ModuleA‘, ‘ModuleB‘]

实际上,在通过angular.module注册了一个模块后,得到一个模块实例,之后调用该模块的controllerfactory等方法的时候,参数中的函数并不会立即执行,而是暂时放在了模块的内部数组中了。

时间: 2024-10-05 22:57:41

AngularJS深入(2)——模块化的相关文章

使用ASP.NET MVC和AngularJS的Web模块化管理

快速浏览标题便了解到本文要谈到公开资源平台,该平台允许快速,轻松地创建一个管理网络,并不需要在风格,导航,解决方案架构和其它跟主要任务无关的琐事上花费过多的时间. 平台视觉图和其中一块模板:(见附图一) 很长一段时间里,我们使用WPF技术模块化管理应用.我们做出的决定是将此管理迁移到网站中.最后我们得出了2个不同的产品:第一个:平台,就是这篇文章致力于介绍的,第二个是用于电子商务应用程序开发使用的集合模块. 技术运用于:(见附图二) 我们决定使用这些技术都是我们广泛应用微软产品的经验结果. 我们

【AngularJS】—— 7 模块化

AngularJS有几大特性,比如: 1 MVC 2 模块化 3 指令系统 4 双向数据绑定 那么本篇就来看看AngularJS的模块化. 首先先说一下为什么要实现模块化: 1 增加了模块的可重用性 2 通过定义模块,实现加载顺序的自定义 3 在单元测试中,不必加载所有的内容 之前做的几个例子,控制器的代码直接写在script标签里面,这样声明的函数都是全局的,显然不是一个最好的选择. 下面看看如何进行模块化: <script type="text/javascript">

AngularJs中的模块化

一个简单的 angularJs 例子如下所示: <!DOCTYPE html> <html ng-app> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <script src="angular.min.js"></script> </head> <b

angularJs中的模块化操作

一.全局的写法 有可能会跟其他程序有冲突 <!DOCTYPE HTML> <html ng-app="myApp"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>无标题文档</title> <script src="angular.min.j

AngularJS基础知识

AngularJS基础知识 --2015.06.28 1.     AngularJS是什么? Angular官网:https://angularjs.org/ ,API: http://docs.angularjs.org/api AngularJS是一个MV*(Model-View-Whatever, 不管是MVC或者MVVM,统称为MDV(Model Drive View))的JavaScript框架,是Google推出的SPA(single-page-application, 单页面应用

从c++看js的那些概念

感觉c++逐渐没落了,js正风生水起,各种概念层出不穷. reactjs,flux ,angularjs cmd,amd模块化设计. 初看起来好像很高端的样子,后来发现也不过是如此. c++毕竟经历了那么久的工业实践考验,许多问题很早就碰到并解决,已经不是问题了. reactjs.angularjs,一个扩展js.一个扩展html,来实现界面和逻辑的分离,以及单向或者双向数据流. 和c++里,最早用代码写界面,最后出现了界面文件.对于界面文件有两种方法,一种是直接把界面编译成代码,一种是在运行时

AngularJs学习笔记7——四大特性之模块化设计

模块化设计 1.引用自定义模块并调用 自定义模块中,如果有一些服务.封装好笑模块,在另外一个模块中(声明的时候,在依赖列表中加入要引入的模块) var app02 = angular.module('fan02',['ng','fan']); 就调用fan02模块中所定义的东西 2.ng内置的模块的用法 (1) ngRoute模块(路由模块) AngularJS是一个开源的js框架.用在数据操作比较频繁的场景下,用于SPA应用 单页面应用的工作原理: 1.页面url:http://127.0.0

AngularJS的模块化操作。

在Javascript中,模块化的开发模式有很多优点,我就在网上找了几点,不管你懂不懂,反正我是不懂模块化开发的. 现在业界比较规范的是AMD,研究模块化开发可以使用比较流行的require.js库来实现模块化的开发,推荐阅读Snandy 的相关系列文章(相当给力):http://www.cnblogs.com/snandy/category/360589.html 使用模块能给我们带来许多好处,比如: 1 : 保持全局命名空间的清洁: 2 : 编写测试代码更容易,并能保持其清洁,以便更容易找到

07模块化-AngularJS基础教程

0. 目录 目录 前言 正文 1 Why use Angular modules为什么使用模块化 2 创建应用模块-Creating the application module 3 加载应用模块-Loading the application module 4 定义控制器-Defining a controller 5 链式定义-Chaining definitions 6 加载模块-Loading modules 10 结论 声明 1. 前言 AngularJS是为了克服HTML在构建应用上