HybridStart是一款基于APICloud的混合应用前端开发框架,提供简洁的引擎能力封装、丰富的UI和插件、清晰的代码管理、简明开发模式,致力于打造最好的多webview混合应用开发体验。
|-- docs/ //文档(开发中移除)
|-- error/ //APP错误页
|-- res/ //APP静态资源
|-- sdk/
| |-- modules/ //js插件
| |-- font/ //字体图标
| |-- core.js //核心库
| |-- server.js //业务方法
| |-- common.js //页面公用代码
|-- loader.js //异步脚本加载器
| `-- ui.css //默认UI
|-- view/ //APP页面(内附示例,开发中移除)
|-- config.js //HybridStart配置
`-- config.xml //APICloud配置
HybridStart 项目主要包括SDK和View两部分。
SDK包含核心库、插件、公用代码、UI;View包含所有APP页面,APP页面体现为一个至少包含temp.html
、style.css
、script.js
三个文件的文件夹,页面文件夹在view/
中最多嵌套两层,即/view/[...]/page/
。
HybridStart 约定APP的生命周期为 `root -> index(exit) <=> page <=> page ...`
,启动页即root
通常没有任何可见内容,只执行APP的状态检测、插件调用、监听、数据初始化等操作,完成后直接跳转到用户可见的首页(index
),首页与展示页之间任意跳转返回,但要在首页拦截返回键,使(安卓)APP无法返回启动页,而是退出APP,整个生命周期内启动页都在后台运行。
appid
信息并清空所有文件docs/
以外所有文件拷贝进来,修改新config.xml里的appid
详细过程参见如何快速开发一款混合应用?。
npm i
安装依赖
npm run init
开启WiFi调试,默认端口8686
npm run sync
增量同步,注意:init
命令将持续占用命令行窗口,此时需要另开一个命令行窗口执行同步操作
npm run stop
关闭WiFi调试
npm run build
编译sdk/ui.less到sdk/ui.css
config.xml包含原生层面的所有配置,详情参考config.xml应用配置说明,另外如果需要应用内升级,请一定记得修改config.xml里的scheme值,否则IOS9以上系统无法升级
<preference name="urlScheme" value="hybridstart" />
<preference name="querySchemes" value="hybridstart" />
config.js
文件是HybridStart的全局配置,所有配置信息挂载在appcfg
对象上,包含APP开发的全部配置,也可以自行扩展其他配置。
默认如下:
host |
请求域名管理
|
||||||||||||||||
set |
APP常规设置
|
||||||||||||||||
ajax |
ajax相关设置
|
||||||||||||||||
loading |
加载动画设置
|
||||||||||||||||
pull |
下拉刷新插件设置
|
||||||||||||||||
plugin |
插件相关设置,便于集中配置插件效果,默认
|
npm i hybridstart
如没有特殊说明,app
对象上的方法均依赖runtime,且支持安卓和IOS双平台。
内部工具包,不依赖runtime,包括选择器及其他常用方法,大部分代码来自mui,建议使用前存为变量var $ = app.util;
$(selector, [context]) |
元素选择器,
|
||||||||||
$.extend(target,source...,deepCopy) |
合并对象,用法同jQuery |
||||||||||
$.each(elements, callback, hasOwnProperty) |
对象、数组遍历方法 |
||||||||||
$.type(obj) |
返回对象类型 |
||||||||||
$.isArray(obj) |
返回对象是否为数组格式 |
||||||||||
$.isPlainObject(obj) |
返回对象是否为纯粹对象 |
||||||||||
$.isFunction(obj) |
返回对象是否为函数 |
||||||||||
$.trim(string) |
返回去除首尾空字符后的字符串 |
||||||||||
$.trigger(element, eventType, eventData) |
触发事件 |
var $ = app.util;
$('#view').on('touchend', '.item', function(i, e){
console.log($(e).data('uuid'));
});
原生runtime就绪回调,显然不依赖runtime。
app.ready(function(){
console.log(api.appId);
});
退出APP,若silent
为真值将没有确认信息直接退出。
app.exit();
接收名称为eventName的事件,并执行回调callback
app.subscribe('hello', function(msg){
console.log('hello ' + msg);
});
发布名称为eventName的事件,附带消息msg,将在接收事件回调中接收
app.publish('hello', 'world!');
APP系统事件监听。
batterylow |
电量低事件,返回格式
|
batterystatus |
电池状态变化事件,返回格式
|
offline |
监听设备断开网络的事件 |
online |
监听设备连接到网络的事件 |
pause |
应用进入后台事件 |
resume |
应用从后台回到前台事件 |
shake |
设备摇动事件 |
app.on('pause', function(){
console.log('app进入后台');
});
手机按键监听。
keyback |
返回键 |
keymenu |
菜单键 |
app.key('keyback', function(){
console.log('按下了返回键');
});
取消事件监听,支持系统事件、自定义事件以及按键监听。
app.off('hello'); //取消自定义事件
app.off('keyback'); //取消按键监听
app.off('pause'); //取消内置事件
获取页面参数,不依赖runtime,仅支持使用app
对象方法打开的页面。
var pageParam = app.getParam();
console.log(pageParam);
跳转/打开页面,leval1和leval2分别代表页面在view/
内的两级文件夹路径,leval2选填,openView将打开路径文件夹内的temp.html
页面,因此view/
内最多支持两级目录。详细参数:
param |
当param不是对象时,将作为参数直接传递给新页面;若为对象类型可以传入更多配置,详见下文;若既不需要传参也不需要修改配置,则要传入 |
param.param |
将传递给新页面的参数,可以在新页面内用 |
param.duration |
页面切换动画时长,单位ms,默认应用全局配置 |
param.anim |
页面切换动画类型,支持类型见app.window.open(),默认应用全局配置 |
param.fullPath |
默认 |
param.pop |
默认 若为 |
param.bar |
默认 若为 |
param.closeself |
默认 |
param.closeback |
默认 |
leval1 |
目标页面在 当leval1是url时,将以web页面形式打开,此时将忽略leval2 |
leval2 |
目标页面在 |
app.openView(null,'news'); //将打开 "view/news/temp.html"
app.openView(null,'news','detail'); //将打开 "view/news/detail/temp.html"
打开/关闭等待提示。
show([msg], [config]) |
显示loading,msg为等待提示文字,默认
|
||||||||
hide() |
关闭loading |
app.loading.show();
setTimeout(function(){
app.loading.hide();
},2000);
设置/复位window或frame的下拉刷新状态。
init(callback) |
初始化下拉刷新功能,callback是触发回调,必填,其他配置见 |
stop() |
停止下拉刷新效果,恢复到正常状态 |
app.pull.init(function(){
console.log('触发下拉刷新');
setTimeout(function(){
app.pull.stop(); //复位下拉刷新状态
}, 2000);
});
打开一个自动关闭的提示消息,config也支持传入整数,表示延时关闭毫秒数。
global |
默认 |
location |
显示位置,默认 |
delay |
延时关闭时间,默认 |
onclose |
关闭回调函数,默认 |
app.toast('hello toast!');
弹出带一个按钮的对话框。msg是提示文字,sureHandle是点击回调,config配置如下:
title |
对话框标题,默认无 |
buttons |
按钮文字设置,默认 |
app.alert('Are you sure?', function(){
console.log('点击确定的回调');
});
弹出带两个按钮的确认对话框。msg是提示文字,sureHandle是确认回调,cancelHandle是取消回调,config配置如下:
title |
对话框标题,默认无 |
buttons |
按钮文字设置,默认 |
app.confirm('Are you sure?', function(){
console.log('点击确定的回调');
}, function(){
console.log('点击取消的回调');
});
弹出一个带两个按钮的输入框,sureHandle是确认回调,cancelHandle是取消回调,回调函数将接收用户输入内容,config配置如下:
title |
输入框标题,默认无 |
title |
输入框提示文字,默认无 |
text |
输入框默认内容,默认无 |
type |
输入框文字内容,默认 |
buttons |
按钮文字设置,默认 |
app.prompt(function(text){
console.log('输入了:' + text);
}, function(){
console.log('取消输入的回调');
});
弹出系统选择按钮框,callback接收点击按钮的序号,config配置如下:
title |
标题,默认无 |
cancelTitle |
取消按钮文字,默认 |
destructiveTitle |
唯一一个红色按钮文字,默认无 |
buttons |
按钮组,必填,例如 |
app.actionSheet({
title: '选择头像',
buttons: ['拍摄', '相册选择']
}, function(idx){
console.log('点击按钮:' + idx);
});
存储/读取值,支持对象类型自动转化。
app.storage.val('test', {a:1});
console.log( app.storage.val('test') ) //{a:1}
删除本地存储key的值
返回本地存储剩余空间,单位byte
清除本地存储,默认跳过appcfg.set.safeStorage
中设置的key,除非force
为真值。
跳转/打开窗口。
name |
窗口名称,不传将自动生成 |
url |
页面url,必须 |
param |
传递给新页面的参数,可以使用 |
anim |
打开窗口的动画效果,默认 |
duration |
打开窗口动画的时长,单位ms,默认 |
app.window.open({
url: '../view/index/temp.html'
});
关闭名称为winName
的窗口,若不传winName将关闭当前window或frame。config配置如下:
anim |
关闭窗口的动画效果,默认 |
duration |
关闭窗口动画的时长,单位ms,默认 |
isFrame |
如果winName是frame的名称,需要设置为真值,默认 |
app.window.close(); //关闭当前window或Frame
窗口事件监听,手势事件支持浮动窗口。
pause |
页面退到后台事件。 |
resume |
页面回到前台或初次显示事件。 |
scrolltobottom |
页面滚动到底部事件。 |
swipleft |
从左向右滑动事件。 |
swipright |
从右向左滑动事件。 |
swipup |
从上向下滑动事件。 |
swipdown |
从下往上滑动事件。 |
app.window.on('resume', function(){
console.log('页面正在前台');
});
在名称为name的窗口,或name窗口内名称为frameName的浮动窗口中,执行脚本scriptContent。
name可以为空,默认当前窗口。
app.window.evaluate('member_index', 'app.window.close()');
打开Frame窗口,Frame窗口的window对象上将扩展selfTop属性,值为自身距离屏幕底部距离。
name |
Frame窗口名称,不传将自动生成 |
url |
Frame窗口url,必须 |
param |
传给Frame窗口的参数,可以使用 |
left |
Frame窗口距屏幕左边缘距离,默认 |
top |
Frame窗口距屏幕上边缘距离,默认 |
width |
Frame窗口宽度,默认 |
height |
Frame窗口高度,默认 |
bottomMargin |
Frame窗口距离底部距离,默认 |
bounce |
Frame窗口是否支持弹动效果,默认 |
app.window.openPopover({
url: './content.html',
top: 40
});
在指定元素区域打开浮动窗口。
id |
指定元素的id,必须 |
url |
打开浮动窗口的url,必须 |
name |
指定浮动窗口的名称,默认使用id作为名称 |
bounce |
浮动窗口是否支持弹动效果,默认 |
param |
传给浮动窗口的参数,可以使用 |
app.window.popoverElement({
id: 'view',
url: './content.html'
});
设置指定浮动窗口的属性。
name |
要修改的Frame窗口名称,必须 |
bounces |
Frame窗口是否有弹动效果 |
hidden |
Frame窗口是否隐藏 |
bgColor |
Frame窗口背景色 |
vScrollBarEnabled |
Frame窗口是否显示垂直滚动条 |
hScrollBarEnabled |
Frame窗口是否显示水平滚动条 |
scaleEnabled |
Frame窗口是否可以缩放 |
rect |
Frame窗口位置及尺寸,格式
|
app.window.setPopover({
name: 'pop_detail',
hidden: true
});
frame窗口动画。
delay |
动画执行延迟时间,单位ms,默认 |
duration |
动画时长,单位ms,默认 |
curve |
动画曲线类型,默认
|
repeatCount |
动画重复次数,默认 |
translation |
位置平移参数,格式
|
app.window.animPopover({
name: 'news_detail',
translation: {
x: 320
}
});
跨域异步请求。
method |
请求方式,默认 |
dataType |
请求数据格式,默认 |
timeout |
超时时间,默认 |
snapshoot |
是否开启快照缓存,默认 |
url |
请求url |
data |
发送数据 |
success |
请求成功回调,接受返回数据 |
error |
请求失败回调,接收错误信息对象,若不传将使用默认错误提示 |
abort() |
中止本次请求。 |
clearSnapshoot() |
清除本请求地址的快照缓存。 |
app.ajax({
url: appcfg.host.control + '/login',
data: {
...
},
success: function(res){
//
}
});
获取设备系统信息。返回数据格式:
{
name: "android", //系统名称
version: "6.1" //系统版本
}
var os = app.device.os();
console.log(os);
获取设备屏幕信息。返回数据格式:
{
resolutionHeight: "1080", //设备高度物理像素数
resolutionWidth: "640", //设备宽度物理像素数
width:"320", //设备宽度像素数
height:"540" //设备高度像素数
}
var screen = app.device.screen();
console.log(screen);
返回设备唯一标识,字符串类型。
var uuid = app.device.uuid();
console.log(uuid);
返回设备型号,字符串类型。
var model = app.device.model();
console.log(model);
返回当前网络连接类型。支持以下类型:
unknown //未知
ethernet //以太网
wifi //wifi
2g //2G网络
3g //3G网络
4g //4G网络
none //无网络
var connect = app.device.connect();
console.log(connect);
拨打电话,默认直接拨打,propt为真值将弹出一个确认提示。
app.device.call('10086');
设置设备休眠状态,keepOn为真值设备将保持常亮。
app.device.setWakeLock(true);
设置应用角标数字。
app.device.setBadge(1);
安装应用。
var os = app.device.os();
var appUri = (os.name==='android' ? 'file://xxx.apk' : 'https://list.kuaiapp.cn/list/KuaiAppZv7.1.plist');
app.device.install(appUri);
内置模块化插件列表,部分插件间存在依赖关系。
内置jQuery 3.x模块化封装。
var $ = require('jquery');
console.log( $ );
表单验证插件,依赖jQuery插件。来自Flow-UI,请求方法用app.ajax()
代替,API及示例参考Flow-UI Validform。
大图全屏播放插件,依赖slide\jQuery插件。来自Flow-UI,针对移动端微调,API及示例参考Flow-UI Album。
辅助方法。来自Flow-UI,API及示例参考Flow-UI Base。
倒计时插件。来自Flow-UI,API及示例参考Flow-UI Countdown。
日期选择器插件,封装AppianZ/DateSelector。
下载插件,返回下载方法。
path |
下载地址,默认 |
name |
存储名称,默认无。 |
onCreate() |
创建下载成功回调,默认 |
onCreateError(err) |
创建下载失败回调,默认 |
onStatus(percent) |
下载进度变化回掉,默认 |
success(savePath, fileSize) |
下载完成回调,默认无 |
error(status) |
下载失败回调,默认
|
abort() |
中止该下载任务。 |
var download = require('download');
download("http://static-zt.oss-cn-qingdao.aliyuncs.com/mock/notice2.zip", {
name: 'download-test.zip',
success: function(savePath, fileSize) {
app.toast('下载完成:' + savePath);
}
});
图表插件,封装百度Echarts。
前端模板引擎,封装百度Etpl。
数字输入插件,依赖jQuery\input插件。来自Flow-UI,API及示例参考Flow-UI inputNumber。
输入框插件,依赖jQuery插件。来自Flow-UI,API及示例参考Flow-UI input。
图片懒加载jQuery插件。来自Flow-UI,API及示例参考Flow-UI lazyload。
选择器插件,封装AppianZ/MultiPicker。
带左划菜单的列表插件,依赖jQuery\etpl插件以及默认UI。
selector |
列表生成容器的选择器,默认 |
multiShow |
允许多个列表项同时显示菜单,默认 |
duration |
回弹时长,字符串格式,默认 |
touchClass |
触摸操作时添加的class,默认 |
data |
返回实例数据。 |
add(newData, prepend) |
向列表末尾追加元素,newData为对象格式,prepend为真值将向列表头部添加元素。 |
set(data) |
重新设置列表数据,data为对象数组,格式见示例。 |
delete(itemIndex) |
删除列表项 |
var $ = app.util;
//列表数据格式
var listData = [{
item: '左滑操作列表0',
className: 'first'
}, {
item: '左滑操作列表1'
}, {
item: '左滑操作列表2'
}];
//侧滑操作列表
require.async('option-list', function(optionList) {
var demo = optionList({
selector: '#controlList',
data: listData,
buttons: [{
text: '编辑'
}, {
text: '添加'
}, {
className: 'btn-danger',
text: '删除'
}],
onClick: function(button, itemIndex, itemLength) {
var optionIndex = $(button).data('index');
switch(optionIndex){
case "0":
app.toast(demo.data[itemIndex].item);
break;
case "1":
demo.add({
item: '左滑操作列表' + demo.data.length
});
break;
case "2":
demo.delete(itemIndex);
break;
default:
console.log('optionlist:error');
}
}
});
});
分页加载插件,来自Flow-UI,API及示例参考Flow-UI pagingLoad。
单向绑定渲染器,依赖jQuery\etpl插件。来自Flow-UI,API及示例参考Flow-UI render。
滚动插件,依赖jQuery\easing插件。来自Flow-UI,API及示例参考Flow-UI scrollCol。
滚动加载插件,依赖jQuery\base插件。来自Flow-UI,API及示例参考Flow-UI scrollLoad。
图片轮显插件,依赖jQuery\base插件。来自Flow-UI,API及示例参考Flow-UI slide。
上传插件,返回上传方法。依赖base插件。语法upload(localImgPath, option)
url |
上传地址,默认无 |
headers |
请求头,对象格式,默认 |
data |
附带参数,json格式 |
onCreate(upId) |
创建上传成功回调,默认 |
onCreateError() |
创建上传失败回调,默认 |
onStatus(percent) |
上传进度变化回调,默认 |
success(remoteUrl) |
上传成功回调,默认无。 |
error |
上传失败回调,默认 |
abort() |
中止该上传任务。 |
require.async('upload', function(uploader) {
uploader('widget://res/img/avat.jpg', {
url: "http://host.refined-x.com/test/fileupload.php",
success: function(newAvat) {
console.log('上传成功:' + newAvat);
}
});
});
基于less实现主题定制,less文件与ui.css
同目录,定制主题需要修改less文件并编译成同名css文件。
内置图标使用阿里巴巴图标库创建,替换图标只需要在平台上自己创建图标项目,将下载的图标文件替换到框架sdk/font/
文件夹中即可。
UI组件示例见演示app。
12列栅格组件,来自Flow-UI,api及示例参见Flow-UI grid。
按钮组件,来自Flow-UI,样式微调,api及示例参见Flow-UI button。
色彩组件,来自Flow-UI,去掉了辅助色(auxiliary),api及示例参见Flow-UI color。
徽标组件
.badge |
定义一个徽标元素 |
.badge-primary |
叠加在.badge上以显示为主色调(另:"success", "info", "warning", "danger") |
列表组件。
.list |
定义一个列表元素,默认内部H标签和p标签将单行显示,超出隐藏。 |
.item |
在.list元素内定义一个列表项。 |
.item-lite |
叠加在.item上使成为一个紧凑列表项。 |
.active |
叠加在.item上显示为点击状态。 |
.item-text-wrap |
叠加在.item上使文字可换行 |
.item-divider |
叠加在.item上使成为带背景的分隔项。 |
.item-note |
在.item内定义一个右侧备注元素。 |
.item-icon-left |
叠加在.item上为左侧图标预留空间。 |
.item-icon-right |
叠加在.item上为右侧图标预留空间。 |
.item-button-left |
叠加在.item上为左侧按钮预留空间。 |
.item-button-right |
叠加在.item上为右侧按钮预留空间。 |
.item-image |
在.item内定义一个图片包裹元素,内部图片将100%填充。 |
.item-avatar |
叠加在.item上为左侧头像图片预留空间。 |
.item-avatar-right |
叠加在.item上为右侧头像图片预留空间。 |
.item-thumbnail |
叠加在.item上为左侧缩略图片预留空间。 |
.item-thumbnail-right |
叠加在.item上为右侧缩略图片预留空间。 |
.item-body |
在.item内定义一个内容块,文字可以换行显示。 |
.item-badge |
叠加在.item上为.badge元素在右侧预留空间。 |
卡片组件。
.card |
定义一个卡片元素,或叠加在.list上成为卡片式列表。 |
card-head |
定义一个卡片头部。 |
card-title |
在卡片头部内定义一个标题。 |
card-foot |
定义一个卡片底部。 |
表单组件。基于.item扩展。
.item-input |
叠加在.item上定义一个输入项,内部input/textarea标签将自动应用样式。 |
.item-stacked-label |
叠加在.item-input上使成为一个带提示文字的输入项。 |
.input-label |
在.item-stacked-label定义一个提示文字元素。 |
.item-checkbox |
叠加在.item上定义一个多选元素项。 |
.checkbox |
在.item-checkbox内定义一个多选状态指示符。 |
.checkbox-primary |
叠加在.checkbox上使指示符应用主色调,可选颜色组件中的所有颜色。 |
.item-radio |
叠加在.item上定义一个单选元素项。 |
.radio-primary |
叠加在.radio上使指示符应用主色调,可选颜色组件中的所有颜色。 |
.item-select |
叠加在.item上定义一个选择项,内部select元素将自动应用样式。 |
开关组件。基于.item扩展。
.item-toggle |
叠加在.item上定义一个开关项。 |
.toggle |
在.item-toggle内定义一个开关。 |
.toggle-primary |
叠加在.toggle上使指示符应用主色调,可选颜色组件中的所有颜色。 |
滑块组件。基于.item扩展。
.range |
叠加在.item上定义一个滑块容器,内部input[type="range"]将自动应用样式。 |
.range-label |
在.range内定义一个内容指示器。 |
Flex栅格组件,来自Flow-UI,样式微调,api及示例参见Flow-UI flex。
比例矩形组件,来自Flow-UI,样式微调,api及示例参见Flow-UI rect。
间距组件,来自Flow-UI,样式微调,api及示例参见Flow-UI space。
工具类。
.fix |
清除浮动。 |
.oh |
超出隐藏。 |
.l/.r |
左/右浮动。 |
.pr/.pa |
相对/绝对定位。 |
.tc/.tl/.tr |
中/左/右对齐。 |
.el |
单行文字,超出显示... |
.hide |
隐藏元素。 |
.hidetext |
隐藏内部文字。 |
.opc0 |
透明元素。 |
.big |
大字号。 |
.small |
小字号。 |
头部组件。
.head |
定义一个头部元素。 |
.title |
定义一个标题。 |
.btn |
.head内.btn:first和.btn:last元素分别显示在头部左侧和右侧。 |
.item-input-inset |
定义一个头部输入框。 |
底部导航组件。
.foot |
定义一个底部导航容器。 |
.tabs |
在.foot内定义一个导航组件。 |
.tabs-ion-top |
叠加在.tabs上显示为带图标的导航。 |
.tabs-text |
叠加在.tabs上显示为纯文字导航。 |
.tab-item |
在.tabs内定义一个菜单项,自适应宽度。 |
.cur |
叠加在.tab-item上显示为当前状态。 |
.active |
叠加在.tab-item上显示为触摸状态。 |
暂无内容组件。
.listPlaceholder |
定义一个暂无内容元素。 |
._container |
在.listPlaceholder内定义一个容器元素。 |
._icon |
在._container内定义一个图片区域。 |
._text |
在._container内定义一个文字区域。 |
图片上传组件,参考示例APP中的图片上传示例。
.picControl |
定义一个图片上传队列组件。 |
.bordered |
叠加在.picControl上显示为带边框组件。 |
._adder |
在.picControl内定义一个添加图片按钮。 |
._pic |
在.picControl内定义一个图片元素,内部需包含img元素。 |
._del |
在._pic元素内定义一个删除按钮,内部需包含.ion图标。 |
._state |
在._pic元素内定义一个上传进度元素。 |
辅助类。
img[data-src] |
懒加载图片默认占位。 |
img[data-remote] |
待缓存图片默认占位,该功能在 |
.onKeyboard |
打开键盘时body自动添加该类,该功能在 |
.block-holder |
将元素/图片修饰为占位元素。 |
框架使用seajs作为脚本加载器,按照约定页面文件和脚本文件位于同目录下,因此页面加载js正常应该在底部这样写:
<script src="../../config.js"></script>
<script src="../../sdk/core.js" id="seajsnode"></script>
<script>
seajs.use('./script');
</script>
但实测发现APICloud引擎有一套页面加载优化机制,打开新窗口时会等待页面脚本执行完毕才启动进场动画,如果页面包含异步数据渲染还需要等待异步内容渲染完毕,以保证页面进场时是完整且稳定的,这套机制带来的问题是打开页面前会有不规则的等待时间,严重时会有卡顿的感觉。
想要绕过这套机制,可以在apiready
回调中动态拼装脚本标签并插入页面,此时页面进场动画已经开始,脚本的执行就不会阻塞进场动画了。框架内置的sdk/loader.js
专门用来实现该功能,只要页面底部引入loader.js就可以非阻塞的加载同目录下指定名称的脚本,例如:
<script src="../../../sdk/loader.js" data-script="script"></script>
使用异步脚本加载器加载的脚本可以直接调用引擎方法,不需要在app.ready()
回调中执行。
因为异步加载时机是`apiready`,导致只有在真机上脚本才能运行,给js调试带来不小的麻烦,推荐大家使用官方IDE开启WiFi调试,这样js中的console信息可以在IDE的console面板中输出,需要注意的是这种方式不支持输出对象类型,当需要输出对象时需要先用JSON.stringify()
将对象转成字符串。
除了js运行中的调试信息外,异步数据的返回结果我们最常需要输出的,我们可以找到框架封装的app.ajax()
方法,在其中处理返回数据处插入一个输出语句,就可以在IDE中输出所有异步请求的返回结果了。
//在sdk/core.js 的大约1277行
...
}else{
opt.data = {
values: opt.data
};
}
console.log(JSON.stringify(opt)) //输出请求参数
api.ajax(opt, function(res, err) {
console.log(JSON.stringify(res)) //输出请求结果
handleRes(res);
handleError(res, err);
});
...
开启请求加密,需要将配置文件中的appcfg.ajax.crypto.enable
设置为true,并填写加密接口appcfg.ajax.crypto.url
,默认使用3DES加密算法,加密密码保存在res/key.xml
中,打包后自动加密,使用apicloud专用api获取。
加密请求将集中发送到加密接口,请求数据格式为:
{
data: secureDataStr, //加密数据
sign: sign //签名
};
加密数据secureDataStr
的生成过程为:先将原请求按如下格式组织:
{
data: opt.data,
url: opt.url
}
再经JSON.stringify
得到原请求数据字符串,然后用3DES方式加密得到加密数据。
签名的生成过程为:将原请求数据字符串与加密密码拼接,取MD5值。
加密接口需要返回3DES加密后的数据字符串,客户端将使用3DES算法解密,并经JSON.parse
解析为json格式,返回给回调函数。
为app.ajax配置snapshoot:true
即可开启快照缓存,即把每一次成功返回的ajax结果保存为快照,下次发起相同请求(判断依据是url和参数相同)时第一时间将快照取出返回给回调函数,待真实数据返回后校验与快照是否相同(需要数据为json格式),若相同则缓存命中,会为对象格式的快照数据添加一个'snapshootEqual'属性值为'true',不同则再次调用回调函数并传入真实数据,为了使业务中能够区分出快照,会为快照数据添加一个'snapshoot'属性值为'true'。
app.ajax({
url: appcfg.host.control + '/login',
data: {
...
},
snapshoot: true,
success: function(res){
//
}
});
默认server.js
中封装了cacheImg()
方法,用于实现图片本地缓存:
/*
* cacheImg(element, callback)
* @element: 目标元素,将自身或子元素的"data-remote"属性值作为图片地址进行缓存,并自动应用到图片的src属性或普通元素的background-image样式。
* @callback: 全部缓存结束后的回调函数
*/
var $ = app.util;
var server = require('sdk/server');
server.cacheImg($('#view'), function() {
console.log('缓存成功!');
});
数据预取通常用来在APP启动时预先获取初始化数据,当需要预取多个数据时候,就需要类似Promise.all()
的功能,但原生的请求方法不支持返回Promise,因此server.js
中封装了一个preGet()
方法,用于获取多个异步数据并回调,预取的数据将存贮在LocalStorage。预取数据需要在server.js
中自行添加。
//在server.js中配置预取请求,数组形式 preGet.prototype.preGetList = [{ key: 'websiteConfig', //预取数据存储key url: appcfg.host.control + '/websiteConfig', //预取数据地址 data: {} //预取数据参数 }];
//数据预取 var server = require('sdk/server'); server.preGet(function(){ console.log('数据预取完成'); });
借助平台的版本管理机制实现APP自动更新,config.xml默认已配置autoUpdate,APP启动时将自动检测新版本并提示,另外server.js中封装了一个checkUpdate()方法,用于应用内手动检测更新。
var comm = require('sdk/server');
comm.checkUpdate();
框架内置基于极光推送实现的推送机制,root页面默认包含推送初始化代码,config.xml中的极光app_key需要自己申请并替换,server.js中封装了push对象,包含open()和close()两个方法,用于实现推送开关,具体实现参见view/member/set/script.js
。