`
rensanning
  • 浏览: 3549170 次
  • 性别: Icon_minigender_1
  • 来自: 大连
博客专栏
Efef1dba-f7dd-3931-8a61-8e1c76c3e39f
使用Titanium Mo...
浏览量:38163
Bbab2146-6e1d-3c50-acd6-c8bae29e307d
Cordova 3.x入门...
浏览量:607339
C08766e7-8a33-3f9b-9155-654af05c3484
常用Java开源Libra...
浏览量:682375
77063fb3-0ee7-3bfa-9c72-2a0234ebf83e
搭建 CentOS 6 服...
浏览量:89382
E40e5e76-1f3b-398e-b6a6-dc9cfbb38156
Spring Boot 入...
浏览量:401867
Abe39461-b089-344f-99fa-cdfbddea0e18
基于Spring Secu...
浏览量:69705
66a41a70-fdf0-3dc9-aa31-19b7e8b24672
MQTT入门
浏览量:91731
社区版块
存档分类
最新评论

Cordova 3.x 源码分析(3) -- cordova.js模块系统require/define

阅读更多
类似于Java的package/import,在JavaScript中也有类似的define/require,它用来异步加载module化的js,从而提高运行效率。
  • define 定义注册一个module
  • require 加载使用一个module
模块化加载的必要性,起源于nodejs的出现。但是JavaScript并没有内置模块系统,所以就出现了很多规范。
主要有2种:CommonJSAMD(Asynchronous Module Definition)。还有国内兴起的CMD(Common Module Definition)

CommonJS主要面对的是服务器,代表是Node.js;AMD针对浏览器进行了优化,主要实现require.js;CMD是seajs

cordova-js最开始采用的是require.js作者写的almond.js(兼容AMD和CommonJS),但之后由于特殊需求(比如模块不存在的时候要throw异常),最终从almond.js fork过来实现了一个简易CommonJS风格的模块系统,同时提供了和nodejs之间很好的交互。在cordova.js中可以直接使用define()和require(),在其他文件可以通过cordova.define()和cordova.require()来调用。所以src/scripts/require.js中定义的就是一个精简的JavaScript模块系统。

源码如下:

// file: src/scripts/require.js

// 定义2个cordova.js内部使用的全局函数require/define
var require,
    define;

// 通过自调用的匿名函数来实例化全局函数require/define
(function () {
    // 全部模块
    var modules = {},
    // 正在build中的模块ID的栈
        requireStack = [],
    // 标示正在build中模块ID的Map
        inProgressModules = {},
        SEPARATOR = ".";

    // 模块build
    function build(module) {
        // 备份工厂方法
        var factory = module.factory,
        // 对require对象进行特殊处理
            localRequire = function (id) {
                var resultantId = id;
                if (id.charAt(0) === ".") {
                    resultantId = module.id.slice(0, module.id.lastIndexOf(SEPARATOR)) + SEPARATOR + id.slice(2);
                }
                return require(resultantId);
            };
        // 给模块定义一个空的exports对象,防止工厂类方法中的空引用
        module.exports = {};
        // 删除工厂方法
        delete module.factory;
        // 调用备份的工厂方法(参数必须是require,exports,module)
        factory(localRequire, module.exports, module);
        // 返回工厂方法中实现的module.exports对象
        return module.exports;
    }

    // 加载模块
    require = function (id) {
        // 如果模块不存在抛出异常
        if (!modules[id]) {
            throw "module " + id + " not found";
        // 如果模块正在build中抛出异常
        } else if (id in inProgressModules) {
            var cycle = requireStack.slice(inProgressModules[id]).join('->') + '->' + id;
            throw "Cycle in require graph: " + cycle;
        }
        // 如果模块存在工厂方法说明还未进行build(require嵌套)
        if (modules[id].factory) {
            try {
                // 标示该模块正在build
                inProgressModules[id] = requireStack.length;
                // 将该模块压入请求栈
                requireStack.push(id);
                // 模块build,成功后返回module.exports
                return build(modules[id]);
            } finally {
                // build完成后删除当前请求
                delete inProgressModules[id];
                requireStack.pop();
            }
        }
        // build完的模块直接返回module.exports
        return modules[id].exports;
    };

    // 定义模块
    define = function (id, factory) {
        // 如果已经存在抛出异常
        if (modules[id]) {
            throw "module " + id + " already defined";
        }
        // 模块以ID为索引包含ID和工厂方法
        modules[id] = {
            id: id,
            factory: factory
        };
    };

    // 移除模块
    define.remove = function (id) {
        delete modules[id];
    };

    // 返回所有模块
    define.moduleMap = modules;
})();

// 如果处于nodejs环境的话,把require/define暴露给外部
if (typeof module === "object" && typeof require === "function") {
    module.exports.require = require;
    module.exports.define = define;
}


其中 factory(localRequire, module.exports, module); 
第一个参数“localRequire”实质还是调用全局的require()函数,只是把ID稍微加工了一下支持相对路径。cordova.js没有用到相对路径的require,但在一些Plugin的js中有,比如Contact.js 中 ContactError = require('./ContactError');

不知道什么原因要把module.exports单做为工厂方法的第两个参数,cordova.js中除了个别地方用到第二个参数(base64.js、uilder.js、modulemapper.js、pluginloader.js、utils.js),大部分都是在用第三个参数在工厂方法里调用module.exports。Plugin的js代码中也基本是module.exports。

参考:
https://github.com/seajs/seajs/issues/588
http://phonegap.com/2012/03/21/introducing-cordova-js/
分享到:
评论

相关推荐

    Cordova 3.x 源码分析(2) -- cordova.js概要

    Cordova 3.x 是一个流行的开源框架,它允许开发者使用标准的Web技术,如HTML、CSS和JavaScript,来构建跨平台的移动应用。在本文中,我们将深入探讨Cordova的核心组件之一——`cordova.js`,它是连接原生移动平台与...

    Cordova 3.x 源码分析(7) -- CordovaLib概要

    这篇名为“Cordova 3.x 源码分析(7) -- CordovaLib概要”的博客文章深入探讨了Cordova的核心组件——CordovaLib。CordovaLib是Cordova项目的基础库,包含了实现Cordova功能的各种模块和插件,如设备API、生命周期...

    Cordova 3.x 基础(10) -- UI框架Ionic Framework

    Cordova 3.x 是一个流行的开源框架,用于构建原生移动应用,利用HTML、CSS和JavaScript等Web技术。它允许开发者使用一套统一的API来访问设备功能,如摄像头、GPS和 accelerometer,从而创建跨平台的应用程序。在...

    Cordova 3.x 实用插件(1) -- Google地图Maps

    Cordova 3.x 是一个流行的开源框架,它允许开发者使用Web技术(如HTML、CSS和JavaScript)来构建原生移动应用程序。在这个特定的教程中,我们聚焦于Cordova 3.x的一个实用插件——Google Maps插件。这个插件允许...

    Cordova 3.x 基础(16) -- slides & books

    在本主题中,我们将深入探讨Cordova 3.x的基础知识,包括其工作原理、安装与配置、插件系统、以及如何创建和发布应用程序。 1. **Cordova简介** Apache Cordova 是Apache软件基金会的一个开源项目,它的核心理念是...

    Cordova 3.x 基础(12) -- Plugin开发

    Cordova 3.x 是一个非常重要的版本,它是Apache Cordova框架的一个早期迭代,该框架允许开发者使用HTML5、CSS3和JavaScript来构建跨平台的移动应用程序。Cordova的核心概念是提供一个“web容器”,将Web应用包装在...

    ionic cordova android安装教程

    ### ionic cordova Android安装教程 #### 一、安装JDK 为了确保Ionic Cordova能够顺利地在Android环境中运行,第一步需要安装Java Development Kit (JDK)。 1. **下载与安装** - 访问Oracle官方网站:...

    Cordova 3.x 入门 - 目录

    Cordova 3.x入门教程是针对移动应用开发的框架,它允许开发者使用Web技术(HTML5、CSS3、JavaScript)来构建跨平台的移动应用程序。Cordova的核心理念是将Web应用封装在原生的移动应用壳中,使得Web应用能够访问设备...

    Cordova 3.x入门

    源码分析部分则是对于想要深入理解Cordova内部原理的开发者准备的,作者细致地解析了Cordova CLI、cordova.js的模块系统、事件通道、本地交互、以及CordovaLib概要等核心内容。 最后,实例开发部分,作者通过基于...

    Cordova 3.x 实用插件(2) -- 二维码Barcode

    Cordova 3.x 实用插件(2) -- 二维码Barcode Cordova 是一个流行的开源框架,用于构建原生移动应用程序,它允许开发者使用Web技术(HTML、CSS和JavaScript)来开发跨平台的应用。在Cordova 3.x版本中,开发者可以...

    Cordova 3.x 基础(7) -- Native API的使用

    **Cordova 3.x 基础:Native API的使用** Cordova,作为一个开源的移动应用开发框架,允许开发者使用Web技术(HTML5、CSS3、JavaScript)来构建跨平台的移动应用程序。在Cordova 3.x版本中,开发者可以通过其提供的...

    Cordova 3.x 实例开发 -- 基于Ionic的Todo应用

    **Cordova 3.x 实例开发 -- 基于Ionic的Todo应用** Cordova是一款开源的移动应用开发框架,它允许开发者使用Web技术(HTML、CSS、JavaScript)来构建原生的移动应用。Cordova 3.x是其早期的一个版本,尽管现在已...

    Cordova 3.x 实用插件(4) -- Android的SEND、VIEW、CALL(WebIntent)

    总之,通过这篇博客,开发者可以学习如何利用Cordova 3.x为Android应用程序添加与操作系统更深度的交互,实现发送数据、查看内容和拨打电话等原生功能。结合提供的源码和工具,开发者能够更好地理解和实践Cordova...

Global site tag (gtag.js) - Google Analytics