Cordova CLI源码分析(三)——初始化

来源:互联网 发布:高中女生必知护肤技巧 编辑:程序博客网 时间:2024/04/29 03:40

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

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)Logdebug信息输出设置判断

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中暴露出必要的参数接口


原创粉丝点击