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

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. shakes hands

    Description On February, 30th n students came in the Center for Training Olympiad Programmers (CTOP) ...

  2. Windows Azure使用体验

    Windows Azure在今年6月6日由世纪互联代理在中国运营,目前只能体验,没有开放注册.不过,体验的门槛比较高,只对企业开放,未来大量对外开放使用貌似时间还早.大家都懂得,“国内门槛高”.本人在 ...

  3. jquery.form.js用法之清空form的方法

    本段代码摘取自jquery.form.js中,由于觉得该方法的使用性非常强,同时也可独立拿出来使用.该段代码言简意赅可以很好的作为学习参考. /** * Clears the form data. T ...

  4. 移动App-UI配制篇

    杂志app-UI配制篇 背景 现在公司有需求是关于杂志app,里面每个页面可能有不同的展现方式,不同的内容,不同的操作方式.那么这里就有一个需求就是根据用户定制这些不同的展现方式,不同的内容,不同的操 ...

  5. php网站共享session方法(相同一级域名)

    这段时间做web开发使用的是php语言 要实现从主站进入子站时无需再登录(如已登录) 使用memcache实现 方法如下 修改php.ini如下 添加 extension=php_memcache.d ...

  6. Delphi的VMT的结构图,很清楚

    Every Delphi class is defined internally by its vmt—​its virtual-method table. The vmt contains a li ...

  7. 与众不同 windows phone (25) - Input(输入)之捕获 UIElement 之外的触控操作, Silverlight 方式捕获手势操作, XNA 方式捕获手势操作, 多点触控

    原文:与众不同 windows phone (25) - Input(输入)之捕获 UIElement 之外的触控操作, Silverlight 方式捕获手势操作, XNA 方式捕获手势操作, 多点触 ...

  8. codeforces 598D Igor In the Museum

    题目链接:http://codeforces.com/problemset/problem/598/D 题目分类:dfs 题目分析:处理的时候一次处理一片而不是一个,不然会超时 代码: #includ ...

  9. [C++]C++中的运行时类型检测

    Date:2014-1-3 Summary: 使用C++中的运行时类型检测.(文章重点在于记录本人的使用情况,并非深层讨论RTTI) Contents:写习惯C#的我,在C++依然存在哪些.NET的惯 ...

  10. SuSE(SLES)安装配置syslog-ng日志server,可整合splunk

    Update History 2014年04月25日 - 撰写初稿 引言 在自己主动化部署AutoYast.自己主动化监控BMC Patrol双方面形成雏形后.日志的收集.管理.分析也顺势成为我们须要 ...