本部分主要涉及以下三个文件

1 cli.js

2 cordova.js

3 events.js

通过前一篇package.json的分析,可以知道,当命令行执行cordova相关命令时,首先调用main参数指向的cordova.js文件,加载模块的相关信息,把内部接口暴露出来,起到初始化作用,方便后续模块内部调用各部分接口;

然后bin 指向的./bin/cordova 文件,执行

1. .#!/usr/bin/env node

2. var CLI = require('../src/cli');

3. new CLI(process.argv);

调用 src/cli,js文件,这个文件才是真正解析命令行参数,并执行对应操作的内容;

cli.js源码

var optimist  = require('optimist'),
cordova = require('../cordova'),
plugman = require('plugman'),
platforms = require("../platforms"); module.exports = function CLI(inputArgs) {
//inputArgs参数是process.argv,命令行参数数组
//第一个元素是node,第二个元素是脚本文件名,第三个元素开始每个元素是运行参数
//所以假设用户输入的是:cordova create hello hellotest com.jinkai.hellotest
//process.argv输出结果是:node cordova create hello hellotest com.jinkai.hellotest
args = optimist(inputArgs)
.boolean('d') //boolean判断命令行参数中是否存在d,如果有args.d返回true,否则false
.boolean('verbose')
.boolean('v')
.boolean('version')
.argv;//args.argv 返回命令参数 if (args.v || args.version) {
return console.log(require('../package').version);
}
//arrayObject.slice(start,end) 方法可从已有的数组中返回选定的元素
//start 必需。规定从何处开始选取。如果是负数,那么它规定从数组尾部开始算起的位置。也就是说,-1 指最后一个元素,-2 指倒数第二个元素,以此类推。
//end 可选。规定从何处结束选取。该参数是数组片断结束处的数组下标。如果没有指定该参数,那么切分的数组包含从 start 到数组结束的所有元素。如果这个参数是负数,那么它规定的是从数组尾部开始算起的元素。
//返回值:返回一个新的数组,包含从 start 到 end (不包括该元素)的 arrayObject 中的元素
var tokens = inputArgs.slice(2), //inputArgs从数组中提取第三个元素(包含第三个)到最后,产生一个新数组
opts = {
platforms: [],
options: [],
verbose: (args.d || args.verbose)
},
cmd; // provide clean output on exceptions rather than dumping a stack trace
process.on('uncaughtException', function(err){
if (opts.verbose) {
console.error(err.stack);
} else {
console.error(err);
}
process.exit(1);
});
cordova.on('results', console.log); if (opts.verbose) {
cordova.on('log', console.log);
cordova.on('warn', console.warn);
plugman.on('log', console.log);
plugman.on('warn', console.warn);
//Remove the corresponding token
//删除token数组中的标识符,即-d ,--verbose这类参数
if(args.d && args.verbose) {
tokens.splice(Math.min(tokens.indexOf("-d"), tokens.indexOf("--verbose")), 1);
} else if (args.d) {
tokens.splice(tokens.indexOf("-d"), 1);
} else if (args.verbose) {
tokens.splice(tokens.indexOf("--verbose"), 1);
}
//arrayObject.splice(index,howmany,element1,.....,elementX) 函数
//index 必需。规定从何处添加/删除元素。
//howmany 必需。规定应该删除多少元素。必须是数字,但可以是 "0"。
//返回值:如果从 arrayObject 中删除了元素,则返回的是含有被删除的元素的数组
} cmd = tokens && tokens.length ? tokens.splice(0,1) : undefined;
if (cmd === undefined) {
return cordova.help();
} if (cordova.hasOwnProperty(cmd)) {
if (cmd == 'emulate' || cmd == 'build' || cmd == 'prepare' || cmd == 'compile' || cmd == 'run') {
// Filter all non-platforms into options
tokens.forEach(function(option, index) { //此处使用forEach遍历元素,不应使用for循环,避免node异步IO机制带来的问题
if (platforms.hasOwnProperty(option)) {
opts.platforms.push(option);
} else {
opts.options.push(option);
}
});
cordova[cmd].call(this, opts);
} else if (cmd == 'create' || cmd == 'serve') {
cordova[cmd].apply(this, tokens);
} else {
// platform/plugins add/rm [target(s)]
var invocation = tokens.slice(0,1); // this has the sub-command, i.e. "platform add" or "plugin rm"
var targets = tokens.slice(1); // this should be an array of targets, be it platforms or plugins
invocation.push(targets);
cordova[cmd].apply(this, invocation);
}
} else {
throw new Error('Cordova does not know ' + cmd + '; try help for a list of all the available commands.');
}
}

源码中加入了必要的注释;

这段代码的主要作用就

1)提取参数,然后调用针对命令参数,分别调用不同接口函数;

2)Log和debug信息输出设置判断

3)栈崩溃信息的美化处理

再来看一下cordova.js文件

var cordova_events = require('./src/events'),
prepare = require('./src/prepare'),
platform = require('./src/platform'),
run = require('./src/run'),
hooker = require('./src/hooker'),
util = require('./src/util'),
path = require('path'),
fs = require('fs'),
compile = require('./src/compile'); var off = function() {
cordova_events.removeListener.apply(cordova_events, arguments);
}; var emit = function() {
cordova_events.emit.apply(cordova_events, arguments);
}; module.exports = {
help: require('./src/help'),
config: require('./src/config'),
create: require('./src/create'),
platform: platform,
platforms: platform,
prepare: prepare,
compile: compile,
run: run,
ripple: require('./src/ripple'),
emulate: require('./src/emulate'),
plugin: require('./src/plugin'),
plugins: require('./src/plugin'),
serve: require('./src/serve'),
on: function() {
cordova_events.on.apply(cordova_events, arguments);
},
off: off,
removeListener:off,
removeAllListeners:function() {
cordova_events.removeAllListeners.apply(cordova_events, arguments);
},
emit: emit,
trigger: emit,
build: require('./src/build')
};

这段代码作用主要有三个:

1)包含依赖文件 require(....)函数部分

2)对node.js事件机制的包装,on 和off两个函数对应绑定事件和移除事件,emit 发射事件,其中cordova_events = require('./src/events') ,调用events.js

var events = require('events');
var emitter = new events.EventEmitter();
module.exports = emitter;

3)Module.exports中暴露出必要的参数接口

Cordova CLI源码分析(三)——初始化的更多相关文章

  1. Cordova CLI源码分析(四)——创建工程

    在第一篇分析我们曾经举例,创建一个新工程, cordova create hello hellotest com.xxx.hellotest cli.js文件分析命令行参数后,会走到 else if  ...

  2. Cordova CLI源码分析(一)——简介

    本系列文章分析基于node.js的命令行工具Cordova CLI,所以如果对node.js基础不是很了解,建议参考http://nodejs.gamesys.net/node-js提供的基础教程 文 ...

  3. Cordova CLI源码分析(二)——package.json

    每个包需要在其顶层目录下包含一个package.json文件,该文件不仅是包的说明,也影响npm安装包时的配置选项 更多参数详见参考文档https://npmjs.org/doc/json.html ...

  4. SpringMVC源码分析--容器初始化(三)HttpServletBean

    在上一篇博客springMVC源码分析--容器初始化(二)DispatcherServlet中,我们队SpringMVC整体生命周期有一个简单的说明,并没有进行详细的源码分析,接下来我们会根据博客中提 ...

  5. SpringMVC源码分析--容器初始化(四)FrameworkServlet

    在上一篇博客SpringMVC源码分析--容器初始化(三)HttpServletBean我们介绍了HttpServletBean的init函数,其主要作用是初始化了一下SpringMVC配置文件的地址 ...

  6. 使用react全家桶制作博客后台管理系统 网站PWA升级 移动端常见问题处理 循序渐进学.Net Core Web Api开发系列【4】:前端访问WebApi [Abp 源码分析]四、模块配置 [Abp 源码分析]三、依赖注入

    使用react全家桶制作博客后台管理系统   前面的话 笔者在做一个完整的博客上线项目,包括前台.后台.后端接口和服务器配置.本文将详细介绍使用react全家桶制作的博客后台管理系统 概述 该项目是基 ...

  7. tomcat源码分析(三)一次http请求的旅行-从Socket说起

    p { margin-bottom: 0.25cm; line-height: 120% } tomcat源码分析(三)一次http请求的旅行 在http请求旅行之前,我们先来准备下我们所需要的工具. ...

  8. SpringMVC源码分析--容器初始化(五)DispatcherServlet

    上一篇博客SpringMVC源码分析--容器初始化(四)FrameworkServlet我们已经了解到了SpringMVC容器的初始化,SpringMVC对容器初始化后会进行一系列的其他属性的初始化操 ...

  9. springMVC源码分析--容器初始化(二)DispatcherServlet

    在上一篇博客springMVC源码分析--容器初始化(一)中我们介绍了spring web初始化IOC容器的过程,springMVC作为spring项目中的子项目,其可以和spring web容器很好 ...

随机推荐

  1. ABAP文件上传下载 用SMW0

    以excel举例 smw0事物代码进入传输模板到服务器上: 下载模板的用到的from代码如下: FORM sub_chek_directory . DATA: l_formkey1 LIKE wwwd ...

  2. Windows 8 动手实验系列教程 实验5:进程生命周期管理

    动手实验 实验5:进程生命周期管理 2012年9月 简介 进程生命周期管理对构建Windows应用商店应用的开发者来说是需要理解的最重要的概念之一.不同于传统的Windows应用(它们即使在后台仍然继 ...

  3. VS2005 MFC 预编译头文件来自编译器的早期版本,或者预编译头为 C++ 而在 C 中使用它(或相反)

    当 Visual C++ 项目启用了预编译头 (Precompiled header) 功能时,如果项目中同时混合有 .c 和 .cpp 源文件,则可能收到 C1853 编译器错误:fatal err ...

  4. A Very Easy Triangle Counting Game

    题意:在圆上取n个点,相邻两个点之间连线,(注意,n和1相邻),然后所有点对(i ,i+2)相连,问能形成的不同的三角形有多少个? 思路:找规律 n=3,cnt=1; n=4,cnt=8; n=5 c ...

  5. address_space 从哪里来

    address_space 从哪里来 这两天想弄清楚linux的内存分配,忽然看到了address_space,就想弄明白. 整个内核就见到 address_space(1)和address_spac ...

  6. html ui设计案例

    1.jquery特效:http://www.5icool.org 2. http://www.open-lib.com/Lib/1992.jsp

  7. Bootstrap表格的使用

    先定义前端table <table class="table table-striped table-bordered table-hover" id="expan ...

  8. 设置 Linux 的 LD_LIBRARY_PATH 变量

    源地址:http://www.cnblogs.com/trying/archive/2013/06/07/3123577.html 我们在ubuntu图形界面下用eclipse写了一个动态库,到cen ...

  9. LCS小结(O(∩_∩)O~吽吽)

    LCS!~如果你在百度上搜这个的话会出来”英雄联盟冠军联赛”,orz..但是今天要讲的LCS是最长公共子序列 ,"Longest Common Subsequence "not&q ...

  10. 运用mapreduce计算tf-idf

    问题描写叙述:给定一个大文件,文件里的内容每一行为:文档名,文档内容. input 文档名1,word1 Word2 ....... 文档名2,word1 Word2 ....... output w ...