鍍金池/ 教程/ 嵌入式/ cordova.js 概要
Cordova CLI
CordovaLib 概要
cordova.js 概要
cordova.js 事件通道 pub/sub
cordova.js 模塊系統(tǒng) require/define
cordova.js 導(dǎo)入、初始化、啟動(dòng)、加載插件
cordova.js 本地交互 JS<->Native

cordova.js 概要

前提環(huán)境:

引用

Platform: android 
Version: 3.4.0

(1)cordova.js/cordova_plugins.js 文件

cordova.js 在創(chuàng)建 Android 工程的時(shí)候,是從 cordova 的 lib 目錄下 Copy 到 platforms\android\assets\www\cordova.js 的。同時(shí)備份到 platforms\android\platform_www\cordova.js

引用

C:\Documents and Settings\RenSanNing\.cordova\lib\android\cordova\3.4.0\framework\assets\www\cordova.js

而 platforms\android\assets\www\cordova_plugins.js 是根據(jù) plugins 文件夾的內(nèi)容生成的。

(2)自己親手生成 cordova.js

Cordova 是 OSS 的,所以可以通過源代碼來生成 cordova.js

a)下載源碼
目前穩(wěn)定版是3.4.0,master 是3.5.0-dev。
https://github.com/apache/cordova-js/tree/3.4.x 下載 cordova-js-3.4.x.zip 解壓到 E:\cordova-js-3.4.x

b)構(gòu)建工具使用的是 Grunt,所以要先安裝 grunt-cli

引用

npm install -g grunt-cli

c)手動(dòng)生成

引用

cd E:\cordova-js-3.4.x 
npm install  --安裝package.json中devDependencies定義的依賴包 
grunt        --運(yùn)行 grunt

d)執(zhí)行后多了2個(gè)文件夾

node_modules 依賴包
pkg
cordova.android.js
cordova.ios.js
...

其中 cordova.android.js 就是我們 Android 工程要用到的 cordova.js 了。

(3)cordova.js 的整體結(jié)構(gòu)

從 E:\cordova-js-3.4.x\tasks\lib\bundle.js 可以看出 cordova.js 的整體結(jié)構(gòu)是:

Js 代碼

// Platform:  <platform>
// <commitId>
/* <license> */
;(function() {
var CORDOVA_JS_BUILD_LABEL = '<commitId>';
// src\scripts\require.js文件內(nèi)容
// 各Module文件內(nèi)容
window.cordova = require('cordova');
// src\scripts\bootstrap.js文件內(nèi)容
})();

其中 Module 來自以下文件:

  • src\common**.js
  • src\android**.js
  • src\cordova.js

各文件輸出形式:

引用

// file: <fileName> 
<fileContents>

最終的 cordova.js:

Js 代碼

// Platform: android
// 3.4.0
/*
 License 省略
*/
;(function() {
var CORDOVA_JS_BUILD_LABEL = '3.4.0';
// file: src/scripts/require.js
//...
// file: src/cordova.js
define("cordova", function(require, exports, module) { /*...*/ }
// file: src/android/android/nativeapiprovider.js
define("cordova/android/nativeapiprovider", function(require, exports, module) { /*...*/ }
// file: src/android/android/promptbasednativeapi.js
define("cordova/android/promptbasednativeapi", function(require, exports, module) { /*...*/ }
// file: src/common/argscheck.js
define("cordova/argscheck", function(require, exports, module) { /*...*/ }
// file: src/common/base64.js
define("cordova/base64", function(require, exports, module) { /*...*/ }
// file: src/common/builder.js
define("cordova/builder", function(require, exports, module) { /*...*/ }
// file: src/common/channel.js
define("cordova/channel", function(require, exports, module) { /*...*/ }
// file: src/android/exec.js
define("cordova/exec", function(require, exports, module) { /*...*/ }
// file: src/common/exec/proxy.js
define("cordova/exec/proxy", function(require, exports, module) { /*...*/ }
// file: src/common/init.js
define("cordova/init", function(require, exports, module) { /*...*/ }
// file: src/common/modulemapper.js
define("cordova/modulemapper", function(require, exports, module) { /*...*/ }
// file: src/android/platform.js
define("cordova/platform", function(require, exports, module) { /*...*/ }
// file: src/android/plugin/android/app.js
define("cordova/plugin/android/app", function(require, exports, module) { /*...*/ }
// file: src/common/pluginloader.js
define("cordova/pluginloader", function(require, exports, module) { /*...*/ }
// file: src/common/urlutil.js
define("cordova/urlutil", function(require, exports, module) { /*...*/ }
// file: src/common/utils.js
define("cordova/utils", function(require, exports, module) { /*...*/ }
window.cordova = require('cordova');
// file: src/scripts/bootstrap.js
require('cordova/init');
})();

define()的順序是在 Grunt 的時(shí)候簡單的按模塊 ID 名升序排的,先后無所謂。
define 只是注冊(cè)模塊,不會(huì)調(diào)用其 factory。
***在 index.html 通過引入cordova.js 后:

Js 代碼

// 加載cordova模塊,賦給window.cordova
// require()第一次被調(diào)用,就開始調(diào)用其factory。
// factory中又包含了其他的require(),就形成了嵌套,直到最后所有module的factory被執(zhí)行完。
window.cordova = require('cordova');  
// 加載Plugin代碼等初期化處理
require('cordova/init');

(4)cordova.js 中個(gè)模塊的說明

平臺(tái)相關(guān)的:

  • src/android/android/nativeapiprovider.js JS->Native 的具體交互形式
  • src/android/android/promptbasednativeapi.js 通過 prompt()和 Native 交互(Android2.3 simulator 的 Bug)
  • src/android/exec.js ****執(zhí)行 JS->Native 交互
  • src/android/platform.js ***bootstrap 處理
  • src/android/plugin/android/app.js 清緩存、loadUrl、退出程序等

通用的:

  • src/common/argscheck.js 用于 plugin 中校驗(yàn)參數(shù),比如 argscheck.checkArgs('fFO', 'Camera.getPicture', arguments); 參數(shù)應(yīng)該是2個(gè)函數(shù)1個(gè)對(duì)象
  • src/common/base64.js JS->Native 交互時(shí)對(duì) ArrayBuffer 進(jìn)行 uint8ToBase64(WebSockets 二進(jìn)制流)
  • src/common/builder.js 對(duì)象屬性操作,比如把一個(gè)對(duì)象的屬性 Merge 到另外一個(gè)對(duì)象
  • src/common/channel.js ****控制事件調(diào)用
  • src/common/exec/proxy.js 用于 Plugin 中往已經(jīng)有的模塊上添加方法
  • src/common/init.js ****初期處理
  • src/common/modulemapper.js ***把定義的模塊 clobber 到一個(gè)對(duì)象,在初期化的時(shí)候會(huì)賦給window
  • src/common/pluginloader.js ***加載所有 cordova_plugins.js 中定義的模塊,執(zhí)行完成后會(huì)觸發(fā) onPluginsReady
  • src/common/urlutil.js 獲取絕對(duì) URL,InAppBrowser 中會(huì)用到
  • src/common/utils.js 工具類

核心:

  • src/cordova.js ****事件的處理和回調(diào),外部訪問 cordova.js 的入口
  • src/scripts/require.js *****模塊化系統(tǒng)
  • src/scripts/bootstrap.js 啟動(dòng)處理(只調(diào)用了初期處理 require('cordova/init');),注意和 platform 的 bootstrap 處理不一樣

(5)cordova_plugins.js 的整體結(jié)構(gòu)

Cordova 從3.0版本開始不再在 cordova.js 中包含各 plugin 的代碼,而是采用 plugman 通過 CLI 生成 cordova_plugins.js 然后動(dòng)態(tài)加載需要的 plugin。3.0之前的代碼結(jié)構(gòu)可以參考:https://github.com/apache/cordova-js/tree/2.8.x lib-/plugin/

Js 代碼

cordova.define('cordova/plugin_list', function(require, exports, module) {
module.exports = [
    {
        "file": "plugins/org.apache.cordova.vibration/www/vibration.js",
        "id": "org.apache.cordova.vibration.notification",
        "merges": [
            "navigator.notification"
        ]
    },
    //.......
];
module.exports.metadata = 
// TOP OF METADATA
{
    "org.apache.cordova.vibration": "0.3.7",
    // ....
}
// BOTTOM OF METADATA
});

其實(shí)也是 define 了一個(gè) ID 為“cordova/plugin_list”的模塊,在初期化的時(shí)候動(dòng)態(tài)加載到 head 里的。Cordova 提供的 Native API 的 js 也是一樣的,可以啟動(dòng)瀏覽器調(diào)試看 HTM L的 Head 部分:

http://wiki.jikexueyuan.com/project/cordova-3.x-primer-source-code/images/2.1.png" alt="picture2.1" />

后續(xù)從四個(gè)方面繼續(xù)分析 cordova.js 中一些核心代碼:

(1)cordova.js 模塊系統(tǒng) require/define

  • src/scripts/require.js 自定義的模塊系統(tǒng)

(2)cordova.js 事件通道 pub/sub

  • src/common/channel.js 發(fā)布/訂閱模式的事件通道

(3)cordova.js 導(dǎo)入、初始化、啟動(dòng)、加載插件

  • src/cordova.js 事件的處理和回調(diào),外部訪問 cordova.js 的入口
  • src/common/init.js 初始化處理
  • src/android/platform.js 平臺(tái)啟動(dòng)處理
  • src/common/pluginloader.js 加載所有 cordova_plugins.js 中定義的模塊,執(zhí)行完成后會(huì)觸發(fā) onPluginsReady

(4)cordova.js 本地交互 JS<->Native

  • src/android/android/nativeapiprovider.js JS->Native 的具體交互形式
  • src/android/android/promptbasednativeapi.js 通過 prompt()和 Native 交互(Android2.3 simulator 的 Bug)
  • src/android/exec.js 執(zhí)行 JS->Native 交互

剩下的代碼就不分析了:

引用

src/android/plugin/android/app.js 
src/common/argscheck.js 
src/common/base64.js 
src/common/builder.js 
src/common/exec/proxy.js 
src/common/modulemapper.js 
src/common/urlutil.js 
src/common/utils.js

下載帶注釋的 cordova.js:這里

參考:
http://www.cnblogs.com/linjisong/tag/PhoneGap/