src/common/init.js 初始化处理
源码:
Js 代码
// file: src/common/init.js |
define("cordova/init", function(require, exports, module) { |
var channel = require('cordova/channel'); |
var cordova = require('cordova'); |
var modulemapper = require('cordova/modulemapper'); |
var platform = require('cordova/platform'); |
var pluginloader = require('cordova/pluginloader'); |
// 定义平台初期化处理必须在onNativeReady和onPluginsReady之后进行 |
var platformInitChannelsArray = [channel.onNativeReady, channel.onPluginsReady]; |
// 输出事件通道名到日志 |
function logUnfiredChannels(arr) { |
for (var i = 0; i < arr.length; ++i) { |
if (arr[i].state != 2) { |
console.log('Channel not fired: ' + arr[i].type); |
} |
} |
} |
// 5秒之后deviceready事件还没有被调用将输出log提示 |
// 出现这个错误的情况比较复杂,比如,加载的plugin太多等等 |
window.setTimeout(function() { |
if (channel.onDeviceReady.state != 2) { |
console.log('deviceready has not fired after 5 seconds.'); |
logUnfiredChannels(platformInitChannelsArray); |
logUnfiredChannels(channel.deviceReadyChannelsArray); |
} |
}, 5000); |
// 替换window.navigator |
function replaceNavigator(origNavigator) { |
// 定义新的navigator,把navigator的原型链赋给新的navigator的原型链 |
var CordovaNavigator = function() {}; |
CordovaNavigator.prototype = origNavigator; |
var newNavigator = new CordovaNavigator(); |
// 判断是否存在Function.bind函数 |
if (CordovaNavigator.bind) { |
for (var key in origNavigator) { |
if (typeof origNavigator[key] == 'function') { |
// 通过bind创建一个新的函数(this指向navigator)后赋给新的navigator |
// 参考:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind |
newNavigator[key] = origNavigator[key].bind(origNavigator); |
} |
} |
} |
return newNavigator; |
} |
// 替换webview的BOM对象navigator |
// Cordova提供的接口基本都是:navigator.<plugin_name>.<action_name> |
if (window.navigator) { |
window.navigator = replaceNavigator(window.navigator); |
} |
// 定义console.log() |
if (!window.console) { |
window.console = { |
log: function(){} |
}; |
} |
// 定义console.warn() |
if (!window.console.warn) { |
window.console.warn = function(msg) { |
this.log("warn: " + msg); |
}; |
} |
// 注册pause,resume,deviceready事件通道,并应用到Cordova自定义的事件拦截 |
// 这样页面定义的事件监听器就能订阅到相应的通道上了。 |
channel.onPause = cordova.addDocumentEventHandler('pause'); |
channel.onResume = cordova.addDocumentEventHandler('resume'); |
channel.onDeviceReady = cordova.addStickyDocumentEventHandler('deviceready'); |
// 如果此时DOM加载完成,触发onDOMContentLoaded事件通道中的事件处理 |
if (document.readyState == 'complete' || document.readyState == 'interactive') { |
channel.onDOMContentLoaded.fire(); |
} else { |
// 如果此时DOM没有加载完成,定义一个监听器在DOM完成后触发事件通道的处理 |
// 注意这里调用的webview的原生事件监听 |
document.addEventListener('DOMContentLoaded', function() { |
channel.onDOMContentLoaded.fire(); |
}, false); |
} |
// 以前版本是在CordovaLib中反向执行js把_nativeReady设置成true后触发事件通道 |
// 现在已经改成在平台启动处理中立即触发 |
// 参考:https://issues.apache.org/jira/browse/CB-3066 |
if (window._nativeReady) { |
channel.onNativeReady.fire(); |
} |
// 给常用的模块起个别名 |
// 比如:就可以直接使用cordova.exec(...)来代替var exec = require('cordova/exec'); exec(...); |
// 不过第一行第二个参数应该是“Cordova”,c应该大写!!! |
modulemapper.clobbers('cordova', 'cordova'); |
modulemapper.clobbers('cordova/exec', 'cordova.exec'); |
modulemapper.clobbers('cordova/exec', 'Cordova.exec'); |
// 调用平台初始化启动处理 |
platform.bootstrap && platform.bootstrap(); |
// 所有插件加载完成后,触发onPluginsReady事件通道中的事件处理 |
pluginloader.load(function() { |
channel.onPluginsReady.fire(); |
}); |
// 一旦本地代码准备就绪,创建cordova所需的所有对象 |
channel.join(function() { |
// 把所有模块附加到window对象上 |
modulemapper.mapModules(window); |
// 如果平台有特殊的初始化处理,调用它(目前来看都没有) |
platform.initialize && platform.initialize(); |
// 触发onCordovaReady事件通道,标示cordova准备完成 |
channel.onCordovaReady.fire(); |
// 一切准备就绪后,执行deviceready事件通道上的所有事件。 |
channel.join(function() { |
require('cordova').fireDocumentEvent('deviceready'); |
}, channel.deviceReadyChannelsArray); // onCordovaReady、onDOMContentLoaded |
}, platformInitChannelsArray); // onNativeReady、onPluginsReady |
}); |