今天是2014年的最后一天,年终总结什么的就不写了。记录一下今天的工作内容。如果不知道phoneGap,那么就不需要往下看了,phoneGap现在已经叫cordova了,叫什么不重要,重要的是它对web移动应用的开发很重要,如果你正在查找关于cordova.js 插件安装方面的工作,那么本文或许对你有用。
cordoval.js目前最新的版本是3.7.0,较之前的2.xxx系列,最大的变化是把功能进行了插件化,或者说是模块化也行。这样做的好处呢是开发者可以按需加载自己的功能插件,减小文件体积,同时也在代码方面做了一些优化,提升了效率。插件化的管理方式,方便进行扩展。
看到有这么多的好处,我们就动心了,直接升级到了3.7.0。可是在升级的过程中,却遇到了不少的问题。这次改造的前端工作,就由我一人全全负责了。从官网下载下来的cordova.js核心文件分成了ios,android等多个版本,而且每个版本都不含有任何插件,比如摄像头,读文件,播放音频等等。所以,改造的第一项工作就是把我们项目中需要的功能插件全部加载上去。
首先提一下我们项目需要用到的插件有播放音频,消息提示,输出日志等。我先是去官网看了一下插件的说明和用法,可是看了半天,也没有找到怎么用的方法,那些插件的说明写的实在是太简单了。没办法,只有去百度了,可是百度来百度去,全是一些过时的用法,难怪别人说查技术资料用百度不靠普。好不容易,找了几篇看上去还算粘边的文章,满心欢喜的照着做了一通,现在想想全是走了弯路。所以这里就不引用它们的教程了。
其实现在回过头来看,只要弄懂一个插件的用法,其它的就触类旁通了。就拿音频插件来说吧。cordova.js 采用了 amd 这种规范,比如定义一个模块用define,调用一个模块用reqiure, 那么要挂载一个插件,肯定要先有一个音频模块。这个在官方的github上有了,直接下载下来,找到对应平台的js文件就行,只是呢添加这个模块有两种方式,一种呢是通过在index.html中用script标签引入的方式,另一种是通过直接在cordova.js中粘贴插件的js源码。我选择的是后一种,但是直接粘贴之后发现,在android真机上调用插件播放声音的时候,eclipse的日志上有错误提示说Media未定义。于是我就纳闷了,仔细看了一下Media.js的源码,大至是这样的:
(function(){ 这里是cordova.js的作用域 .................var utils = require('cordova/utils'), exec = require('cordova/exec'); var mediaObjects = {}; /** * This class PRovides access to the device media, interfaces to both sound and video * * @constructor * @param src The file name or url to play * @param successCallback The callback to be called when the file is done playing or recording. * successCallback() * @param errorCallback The callback to be called if there is an error. * errorCallback(int errorCode) - OPTIONAL * @param statusCallback The callback to be called when media status has changed. * statusCallback(int statusCode) - OPTIONAL */ var Media = function(src, successCallback, errorCallback, statusCallback) { // successCallback optional ................ module.exports = Media;
这里其实只要把Media前面的var去掉,就可以把Media提升为全局变量,但是当时我居然没有看出来。不过这样也不是一个好的解决方案,因为cordova的核心功能都是用
define定义的,我这样直接添加功能代码,显然与作者的插件化思想是相背离的。于是呢,我就参考以前版本的写法,用define进行了定义。变成如下这个样子:
define("cordova/plugin/Media", function(require, exports, module) { var Media = function....
module.exports = Media;});
可是问题又来了,这样做还是只是定义一件插件而已,怎么去调用它呢?其实真的很简单,直接在cordova.js末尾,也就是 cordova = require('cordova')后面加一个Media=require('cordova/plugin/Meida');就可以了。当时我怎么就没有想到呢。可能是太过相信cordova的插件机制了,它还没有这么智能。不过呢,这还没有完,想想ios我们也是要兼容的,所以ios平台对应的代码也要加上。cordova为什么不把各个平台通用的部分提出来呢?这样的话,对于兼容多个平台的情况,cordova的体积又可以大大减小了。
吐糟归吐糟,后继的工作还是要做好,陆续把其它的插件也补上。不过呢,我要在此多说一句,别只顾着复制粘贴,有些内容需要根据实际情况进行修改一下。比如console.log这个插件,用define进行包装的时候,为了统一,最好都写成
define("cordova/plugin/xxx")的形式,这样维护的时候一看就明白了. 还有一个好处就是可以方便插件机制进行自动化加载,不过这个好处我还没有研究透,等看懂源码再细说。另外还有一个坑,有一处代码调用了require("cordova/plugin_list")这样的代码,但是却没有看到定义的地方,比如说define("cordova/plugin_list"),虽然在eclipse上编译安装的时候,生成apk没有问题,真机上也正常用行了,但是java那边的兄弟说在服务端打包的时候会报错,说找不到plugin_list.js这个文件。所以需要补上这个定义:
define("cordova/plugin_list",function(require, exports, module){ var plugin_list = []; module.exports = plugin_list;})
大致就是这么一个东东,具体的代码我不记得了,反正github上是有的下的。
最后呢,关于这个require/define的用法,我专门抽出来,然后进行了一些简化,方便大家直观的理解它的运行原理,如果觉得好,还可以在自己的项目中直接使用。
项目地址:https://github.com/bjtqti/mini-require
好了,总算写完了。掌声送给自己!
新闻热点
疑难解答