篇头语: 非常感谢APICloud官方给我版主职位,每天都看到很多朋友提出很多问题,我就借此机会写了一系列的教程,帮助大家从小白到高手之路。系列名称:《APICloud之小白图解教程系列》,会不定时的更新! 前言: 世界在改变,一切在移动化!可以说现在是移动互联网的时代,很多东西只需要一个APP就可以解决,富有:“秀才不出门,便知天下事”之说! 移动APP分类 1、Web APP:使用HTML/HTML5,CSS/CSS3、Javascript/ECMAScript开发的网站,在手机浏览器端运行的。简称WEB应用 2、Native APP:使用Java,Object/Swift,C#等原生编程开发的手机客户端应用,简称本地应用或原生应用。 3、Hybrid APP:使用HTML/HTML5,CSS/CSS3,Javascript/ECMAScript等前端语言+原生SDK模块开发的手机客户端应用,简称混合应用 而APICloud正是Hybrid APP。 这么多种APP开发模式,我们到底选那个? 很多人会问这样的问题?都是APP,我学哪个啊?这个就要问问你自己,你要从事哪一方面的开发。如果是想做手机网站方向的,可以学Web APP开发,如果想做移动客户端的应用,就从事Hybrid APP或者Native APP开发。 我这里比较推荐大家学习Hybrid APP开发。为什么呢?有以下几点: 1、学习成本低,无需学习Java,Object-C/Swift,C#等编程语言。只需学习前端语言即可。 2、无需了解大量的第三方框架。 3、Hybrid APP目前的性能已经无限接近Native APP。 4、手机客户端淘宝和百度客户端就是Hybrid APP开发的。 5、开发速度快,成本低,高回报! 6、如果您是企业的话,可以省了很多开发成本和开发周期。 我想,看到这里,大家应该都明白了吧! 为什么选择APICloud? 这个问题是个好问题,我想大家都想知道为什么选择APICloud,而非其他平台。下面我就给大家分析一下吧 目前主流的Hybrid APP开发平台有:PhoneGap,AppCan,HBuider(HTML 5+),APICloud,Wex5等,下面我就个人学习得到的经验分享给大家,为什么我选择APICloud! 各自突出优点: 1、PhoneGap:可以开发跨平台的APP,包括IOS,Android,Palm,Symbian、Palm等平台的应用。大量是原生SDK的支持和非常活跃的社区和视频教程。 2、AppCan:可以开发跨平台的APP,目前能开发IOS,Android两大平台,内置了前端框架,也有很多模块供开发使用,免安装的IDE,内置智能提示,社区也较活跃。 3、HBuider:说到HBuider不得不说它的IDE非常的强大,这个是不可否认的,它的优点可以开发IOS和Android两大平台的开发,包含Hello Mui前端框架和HTML 5+原生态的API和30多万个API的Native.js。 4、APICloud:独树一帜的云平台,无需配置IOS和Android的开发环境即可编译成安装软件,免安装的IDE,和强大的模块支持和非常活跃的社区。社区中有很多新手教程,视频,和官方开源的DEMO案例。定期还有公开课和讲座。而且支持主流的IDE开发,无需APICloud Studio。官方的文档非常齐全,基本案例复制都能直接使用,这些是其他平台做不到的。 5、Wex5:非常牛逼可视化的IDE设计器,无需任何HTML基础就可以构建APP页面,使用Cordova开源框架,有大量的原生API的支持。使用者较少。 各自缺点: 1、PhoneGap:需要配置原生态的环境,而且懂原生态的语言才能开发,官方的文档全部是英文的。(这是对国人大部分来说致命的缺点) 2、AppCan:编译时需配置原生态的环境,通过它开发出来的APP过分像网页,切换视图流畅性不强,社区没有大神。。。。。很多问题都是待解决的问题,模块应用也少,即时通讯都没有。。。。 3、HBuider:编译时需配置原生态的环境,Native.Js需会原生态的语言才能写,这又是一个坑,社区半死不活的。模块只能自己去引用和开发。。。。。 4、APICloud:IDE提示不好,部分第三方模块存在很多新手坑,新手上手不易,添加模块都需云编译和编译自定义Loader才能使用,模块还不是很完善,部分常用模块收费。 5、Wex5:编译时需配置原生态的环境,开发的APP体验性不好。切换有点卡卡的。Cordova技术需要原生态语言的基础。 我想综合上面所示,大家应该心里有一定的想法了,真正好用的平台就是无需编译环境,无需编程基础,社区活跃,官方提供大量支持,有很多大神在!我想,非APICloud莫属了! APICloud该怎么学,怎么使用? 这个问题是很多第一次接触APICloud的人都会问的问题,打开http://www.apicloud.com的官方网站,看到菜单有云API,端API,...价格(一开始会以为是收费软件)等等,看到这些菜单会有点懵。什么是云API,又什么是端API,一大推问题随之而来。 好了,我就和大家说说学习APICloud其实只需要了解以下东西即可: 1、IDE:用来写代码的编程软件,例如:APICloud Studio,下载地址:http://docs.apicloud.com/APICloud/download, 注:APICloud SDK是APICloud提供的完整的开发环境。包含APICloud Studio、AppLoader、FrameWork、Document等。我们用来写代码的是APICloud Studio 2、控制台:这个是APICloud非常牛逼的地方,那什么是控制台?你通过IDE写好了代码之后,是不是要编译成APP来安装?也就是所谓的发布,那就是它了,控制台的地址:http://www.apicloud.com/console,控制台可以做什么呢?比如编译成APP,设置APP图标,是否显示状态栏,设置APP权限(比如是否可以打电话,定位等),可以向客户发布更新,添加第三方模块等等。 3、端API:这个是学APICloud必须学的东西,那它又是什么呢?其实就是一个api库,主要是通过js调用原生APP的东西,所有的端API的格式都是以 【api.方法名称】,回调函数(也就是调用之后要实现的功能)都是返回(ret,err)两个参数,比如弹出信息使用api.alert,打开窗口api.openWin 4、模块:这个东西很多新手都很不懂,什么是模块?可以用句话说,就是别人开发的东西,我拿来用。例如:支付宝,QQ登录,微信分享,二维码扫描,百度导航等。我们的APP经常需要用到其他这些人家开发的东西,那就是要使用模块了,APICloud的模块也非常规范,都是使用api.require("模块名称")来使用,需要注意的是:需要在控制台添加第三方模块,和云编译使用(也可以使用IDE中的编译自定义Loader使用) 5、云API:这个其实就是给没有编程基础的朋友使用了,里面包含云数据库,检测更新等等功能,这里只介绍一下。后期会有一篇文章详细介绍。 辅助学习方法: 1、APICloud的官方文档:http://docs.apicloud.com/,你要利用好搜索功能,在文档中有一个全局搜索功能,不懂哪个方法或者模块的调用应搜索一下。(个人建议,学习之前应系统的将文档看一遍) 2、APICloud社区:http://community.apicloud.com/bbs/forum.php, 很多问题都可以通过搜索得到答案 3、社区推荐的新新手教程:http://community.apicloud.com/bb ... 7926&extra=page%3D1 这里有很多新手遇到的问题 4、官方开源的源码和视频教程:http://docs.apicloud.com/APICloud/videos-and-codes 直接下载源码下面学习上手比较快 APICloud设计模式,这个非常重要,大部分页面都是这种形式打开,头(window),身体(frame,页面) 我相信很多人一开始学习APICloud的时候都会被Window,Frame,FrameGroup给搞懵,什么时候应该用Window,什么时候应该用Frame,这里我就解释一下: 1、window:就是当前显示在APP最前面的窗口,也是面对我们的窗口 2、Frame:Frame就是窗口里面的框架,好像HTML中的Iframe一样, 3、FrameGroup:FrameGroup就是框架组合,好像HTML中的选项卡。 可以举个更形象的例子,比如我们打开谷歌浏览器,默认就会打开首页标签,那这整个标签就是Window,而打开的页面就是Frame,如果点击了一个链接,那就是打开新的标签,也就是打开一个Window(标签),Window下面有Frame(页面)。这样大家就明白了。不同的是,APICloud的window可以有多个Frame。 下面我给一张图解说一下APICloud打开标签的方式(也就是打开Window,Window下面有Frame(页面) 这样大家就明白了,我们要使用一款APP,首先要点击APP图标(点击电脑的浏览器图标),然后打开第一个窗口Window(也就是浏览器默认打开第一个页面首页),打开窗口之后就创建头部(也就是浏览器的标签),然后再打开页面Frame(就是我们访问的页面) 这样大家应该清楚的明白了吧。 好了,第一篇认识APICloud的教程就结束了,下一篇系列教程为 《APICloud之小白图解教程系列(二):APICloud Studio的使用和简单布局篇》 |
前面一篇主要讲了项目的创建和布局方式。总结一下APP的布局方式最佳为win+frame,多写个文件多弄点优化才能让你的APP流畅度提高。 这篇主要来讲一下模块的引入、服务器数据对接及APP数据存储方式。 一、模块的引入和使用 在apicloud的模块store里面提供了大量的模块,我们可以直接在html里面引入使用 使用方法: 在需要使用模块的页面中加入: var obj = api.require('模块名'); 然后参考对应模块的使用方法。如果在一个页面中频繁使用到一个模块的功能,最好就将其声明称全局变量。 二、服务器数据对接---云数据库和本地服务器 1、在APICLOUD开发的过程中,我们看到了一个新名词,数据云。这个是apicloud提供给开发者的一个云数据库,我们可以利用它来完成数据的存储和读取。 开启数据云流程, 进入控制台---左侧云设置----选择一个储存服务--确定即可开通,然后在Database里面我们会看到默认的几张表 (以下注释非官方注释,个人理解的意思 *.*) accessToken ---- 存储用户令牌类 file ---- 文件类 role ----- 角色配置 roleMapping --- 相关对应的角色权限 user ----- 用户 (默认的表前面有个下划线不用理会他,就当不存在哈) 当然我们也可以根据自己的需求创建各类表,通过添加列来自己表字段,注意根据自己需求设置下字段类型,字段类型不懂的可以百度一下,主要有字符,数字,时间,文件,数组,关联等 对于数据表的操作说简单的点就是增删改查,下面说一下数据云的使用方法,在文档里面对应(mcm) 我们通过model模块来实现数据云的操作,首先引入和配置下model模块 var model = api.require('model'); model.config({ appKey: 'A991A337-0212-A29D-0C9C-A518E39FXXXX', host: 'https://d.apicloud.com' }); appKey 可以在控制台里面查看。 然后通过model的各种方法来实现增删改查 例子,插入数据 var model = api.require('model'); model.insert({ class: '表名', value: { 字段: '值' } }, function(ret, err){ if(ret){ //do something } }); 其他的方法请参考: http://docs.apicloud.com/%E7%AB%AFAPI/%E4%BA%91%E6%9C%8D%E5%8A%A1%E5%AF%B9%E6%8E%A5/mcm#a2 TIP:在apicloud,一般用ret来标识成功的返回,err表示错误 在表的操作中数据返回的是JSON格式,我们拿到这个JSON数据后就开始用js来处理,插入到html元素中 自己可以建个表,按照文档来试一下各种方法。 2、从自己的服务器读写数据 apicloud封装了一个ajax的方法来方便我们通过post或get等获取服务器数据,获取的数据类型有json和text格式,使用方法跟JS原生和jq的post get 大同小易 重点来说一个几个注意的地方 当使用post时,发送的数据要写在data的values里面。 当为get时,data是不起作用的,发送的数据放在url里面 以php为例接受时直接 $name = $_POST['name']; 三、APP数据存储方式 在apicloud的数据方式还是蛮多的,上面的数据云和自己服务器算是两个吧,下面还有H5的本地保存,读写文件方式,设置偏好值等。 1、H5本地保存 localStorage 在apicloud中已经封装的更简单了 $api.setStorage('name','key');//设置 $api.getStorage('name');//获得指定name的值 $api.rmStorage('name');//清除指定name的值 $api.clearStorage();//清楚全部本地数据 不过这个方式不建议大数据的读取,可以用来存取用户的基本信息 文档 http://docs.apicloud.com/APICloud/%E6%8A%80%E6%9C%AF%E4%B8%93%E9%A2%98/framework-dev-guide#39 2、文件存储方式 readFile和writFile fs模块 如果不牵扯到文件的修改的话建议使用readFile和writeFile,操作还要方便些。 这些主要用在保存大数据和保存内容缓存,保存文件的时候个人觉得保存到缓存文件夹里面,获取方式 var cacheDir = api.cacheDir; 例子,比如我们要将内容列表写到本地,然后将列表的内容分别保存一个文件,下次打开APP的时候先查询有没有对应的本地文件,没有的话或者有更新再从服务器读取 以JSON数据为例:得到JSON数据后 var cacheDir = api.cacheDir; api.writeFile({ path: cacheDir+'/自定一个文件名.json', data: JSON.stringify(josn) }, function(ret, err){ }) 注意要将json转为字符串,否则无法写入,(不转换的话安卓设备可以写入,IOS上是不行的) 读取: api.readFile({ path: cacheDir+'/文件名.json' }, function(ret, err){ if(ret.status){ var jsonData = JSON.parse(ret.data); } }); 注意读的时候将数据转为对象 3. 此外apicloud还提供了api.setPrefs的方法来设置偏好值 参考文档:http://docs.apicloud.com/%E7%AB%AFAPI/api#45 到此数据这一块的处理又差不多到一阶段了,多多动手才能发现问题,发现了才能去解决。我提供的只是一种思路方式,关键还得靠大家。谢谢 下一篇将介绍 APP 优化的处理, 新手入门教程,从0开始入手APIcloud(一) 新手入门教程,从0开始入手APIcloud(二) 新手进阶教程,从0入手APICloud(三)-- 缓存方案 |
前两篇的入门教程相信大家已经对APICLOUD如何开发一个APP有了了解,当然这只是个教程,更多的是大家动手练习。 今天给大家带来的是进阶性的教程了,利用文件缓存存储充分发挥你的APP性能,提高用户体验度。一个好的APP不是单纯的几个JS就搞定的,我们得多动手多写点东东来优化,提高用户的体验,这个过程是比较繁琐的,大家可以跟自己的团队一块协商更好的优化解决方案。 我们在使用一些APP的时候会发现从列表页打开内容页基本是秒开;使用QQ或微信上传多图时也没有图片的等待效果。下面我们就围绕着这两个案例来讲解。 一:列表页和内容页的文件缓存存储方案 先看一个流程图: 借着上面的流程图我们对开发思路先有个了解,我们存储的时候可以选择一些比较死的数据来存储,比如用户发布一条动态后,用户的信息和动态内容数据是死的,回复点赞等信息是更新繁琐的,我们就可以将用户的基本信息和动态基本内容保存到本地。 实现此功能用到的主要方法为 writeFile和readFile,在存储数据时注意转换JSON数据为字符串,读取的时候在将其转换为对象,下面开始说一下基本代码,主要讲一下内容页这块的存储,列表也存储相对要简单点,留给大家作为作业来练习 列表页实现代码: 声明两个全局标量page和lastId。同时还声明了要一个lock变量,防止滚动加载时重复 var page=1,lastId=0,lock=false; 使用ajax从服务器获取数据 我写了个ajax的通用方法,我们下面讲的就数据读取就全部用这个来, function ajaxRequest(url, method, datas, callBack) { var serverUrl = 'http://www.xxx.com/'; var now = Date.now(); api.ajax({ url: serverUrl + url, method: method, cache: false, timeout: 30, dataType: 'json', data: { values: datas } }, function (ret, err) { callBack(ret, err); }); } 下面在代码中注释说明实现 function getData(){ var getDataUrl = '你的URL&page='+page; ajaxRequest(getDataUrl, 'GET', '', function (ret, err) { if (ret) { //获得最后一条数据id,主要是判断下拉刷新的时候用 if(ret[0].id>lastId){ lastId = ret[0].id; } var html = ''; for(var i in ret){ /*下面就是往容器里面插入数据的代码*/ html += '<div id="'+ret.id+'">'; /*.......*/ html += '</div>'; } /*下面这块代码根据自己的实际情况来写*/ if(page>1){ //el为你的容器 //当页数大于第一页的时候,在最后一个子元素后面插入HTML $api.append(el,html); lock = false; }else{ //其他直接写入,这个 $api.html(el,html); lock = false; } //将数据内容写入本地文件的一个函数,这里的ret是个多维数组 writeFile(ret); } else { // do } }) } //将列表数据写入缓存文件 function writeFile(json){ //缓存目录 var cacheDir = api.cacheDir; for(var i=0;i<json.length;i++) { //内容的ID var id = json.id; //内容的数据,内容的数据存储时就根据自己的需要来看存储哪些,可以循环过滤一下 var dataJson = json; //写入文件 api.writeFile({ //保存路径 path: cacheDir+'/'+id+'.json', //保存数据,记得转换格式 data: JSON.stringify(dataJson) }, function(ret, err){ }) } } 这样内容就分别存储到本地里面,其他下拉刷新,滚动加载会在整理到后面的JS文件里面 注意上面保存的文件名是用id来保存的,也可以根据自己的需要来加前缀或者目录。 在打开内容页的时候我们一般是在onclick加上内容ID,来判断。我们就根据这个id首先来判断有没有本地存储文件,没有的话再从服务器获取。 内容页JS实现代码 function getData(){ var cacheDir = api.cacheDir; api.readFile({ path: cacheDir+'/'+id+'.json' }, function(ret, err){ if(ret.status){ //如果成功,说明有本地存储,读取时转换下数据格式 var jsonData = JSON.parse(ret.data); //自己写操作json的代码啦 }else{ //如果失败则从服务器读取,利用上面的那个ajaxRequest方法从服务器GET数据 } }); } 注,上面的getData放在对应页面的apiready里面 是不是看着相当的简单,主要是一种思路,多写点代码就能让用户体验度提高一点 下面再来点复杂点的 二,用户大数据静默上传方案 在APP中我们会做到这样一个功能,用户多图上传。而现在随着手机像素越来越高,图片越来越大,本身手机网络速度有限,上传多张照片的时候是非常困难的,尤其是等待时间。总不能让用户发个东西在那傻傻的等待吧,下面提供一个简单解决思路,同样主要还是利用writeFile和readFile来实现,同时利用了大量的监听事件。 先看图 里面有几个知识点,sendEvent 、 addEventListener、 图片压缩上传 我们理下思路: 用户发布完数据后先写入本地文件并同时给列表页发送要给监听事件。当列表页收到监听这个事件后开始读文件并将本地的数据先插入列表页(这里插入的时候可以给列表页加个同步至服务器的loading动画),然后开始与服务器同步数据(基本信息写入,图片压缩后上传)。上传成功后再来删除文件刷新列表页等操作。 数据写入到本地和读取这个就不用多说了吧,按照上面说的writeFile和readFile来实现 当写入成功后加一个sendEvent事件 var cacheDir = api.cacheDir; api.writeFile({ path: cacheDir+'/waiting'+date+'.json', data: JSON.stringify(data) }, function(ret, err){ if(ret.status){ //发送个事件 api.sendEvent({ name: 'waitUpload', extra:{fileName:'waiting'+date} }); api.toast({ msg: '发布成功', duration:1500, location: 'top' }); setTimeout(function(){ api.closeWin({ name: '' }) },1000); }else{ api.toast({ msg: '发布失败', duration:2000, location: 'top' }); } }) 回到列表页在apiready里面来监听这个事件 apiready = function(){ //监听最新发布(本地缓存) api.addEventListener({ name:'waitUpload' },function(ret){ if(ret && ret.value){ var value = ret.value; var cacheDir = api.cacheDir; api.readFile({ path: cacheDir+'/'+value.fileName+'.json' }, function(ret, err){ if(ret.status){ //如果监听到事件,先利用readFile来读取数据并写入到列表页,就省略这块了 //加了个延迟来同步服务器,传入数据,我这里的数据后面加了个0,因为在开发的时候我用了doT模板引擎,在发布保存的时候我组装的是一个多维数组,然后这里只取了第一个数组。 setTimeout(function(){ synchroServer(newDataArr[0]); },500) } }); } }) } 同步到服务器,在服务器数据库里面我是这样来实现的 分表一个是基本数据表和一个图片表) 基本数据传完后返回一个内容ID,然后开始处理图片数据,先压缩图片,然后转为base64来上传,上传时同时传递了内容ID。 上传图片是循环上传的,记录一个上传图片成功的次数,如果这个次数等于图片数量就表示成功了,然后执行全部数据上传完成的操作。我这里没有做断点续传等类的操作,自己可以扩展下,。这里还是用里fs模块来执行删除文件,直接贴代码,在代码里面说明 function synchroServer(data){ var fs = api.require('fs'); isSynchro = true; postDataUrl = '';//基本数据发送的URL var updatePhotosUrl = '';//图片上传类的URL ajaxRequest(postDataUrl, 'post', data, function (ret, err) { if (ret) { if(data.photos.length>0){ /*如果有图片*/ //这里是我在自己的项目中写一个状态的判断,保留了一下 var loadingName = $api.byId('loading-name-waiting'+ret.synchrotime); $api.text(loadingName,'上传图片'); //循环执行图片的压缩和上传操作 for(var i in data.photos){ var img = new Image(); img.src = data.photos;//图片路径 img.onload = function () { var that = this; //生成比例 var w = that.width, h = that.height, scale = w / h; w = 640 || w; h = w / scale; //生成canvas var canvas = document.createElement('canvas'); var ctx = canvas.getContext('2d'); $api.attr(canvas,'width',''+w+''); $api.attr(canvas,'height',''+h+''); ctx.drawImage(that, 0, 0, w, h); var base64 = canvas.toDataURL('image/jpeg', 1 || 0.6 ); var upData = { userid: userid, dynamicid: ret.id, base64: base64 } //上传 ajaxRequest(updatePhotosUrl, 'post', upData, function (retI, errI) { if(retI){ //全局变量记录成功次数 uploadNum += 1; if(uploadNum==data.photos.length){ //全部完成后 $api.text(loadingName,'上传完成'); uploadNum=0; isSynchro = false; //删除正在上传的dom,并刷新 setTimeout(function(){ var dynamicIng = $api.byId('dynamic_waiting'+ret.synchrotime); $api.remove(dynamicIng); //这是一个等于下拉刷新的方法,自己可以根据前面说的lastId来判断实现 getNewData(); //删除本地缓存文件 fs.remove({ path: api.cacheDir+'/dynamic/waiting'+ret.synchrotime+'.json', },function(ret,err){ }); },1000) } } }) } } }else{ //如果没有图片的操作,根据上面自己去写 } } else { } }) } |