zoukankan      html  css  js  c++  java
  • Cordova CLI源码分析(三)——初始化

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

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


  • 相关阅读:
    CentOS中JAVA_HOME的环境变量设置
    Macserver服务更新经常使用的几个shell命令
    一个技术派创业者的反思
    巴斯卡三角形
    iOS中基于 Socket 的 C/S 结构网络通信(中)
    poj 3267 The Cow Lexicon (动态规划)
    Android入门:短信和拨打电话
    HDUOJ--4888--Redraw Beautiful Drawings【isap】网络流+判环
    Dynamics CRM 2015 New Feature (9): Services Changes
    Class 找出一个整形数组中的元素的最大值
  • 原文地址:https://www.cnblogs.com/riskyer/p/3289998.html
Copyright © 2011-2022 走看看