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


  • 相关阅读:
    不常用的cmd命令
    js获取宽度
    Marshaling Data with Platform Invoke 概览
    Calling a DLL Function 之三 How to: Implement Callback Functions
    Marshaling Data with Platform Invoke 之四 Marshaling Arrays of Types
    Marshaling Data with Platform Invoke 之一 Platform Invoke Data Types
    Marshaling Data with Platform Invoke 之三 Marshaling Classes, Structures, and Unions(用时查阅)
    Calling a DLL Function 之二 Callback Functions
    WCF 引论
    Marshaling Data with Platform Invoke 之二 Marshaling Strings (用时查阅)
  • 原文地址:https://www.cnblogs.com/riskyer/p/3289998.html
Copyright © 2011-2022 走看看