组件是AppWorker的基础,平台根据Android,IOS的SDK抽象了一套统一的javascirpt库,把所有组件分三种类型(UI
,MM
,SM
),这三种组件都有自己的属性,事件,方法,其他所有组件(目前大概有200)都是这三种组件的子类,继承了父类的属性,事件和方法。应用开发者只需要了解基本的javascipt知识和我们提供的这套API规范,就可以开始开发移动应用了。
AppWorker目前只支持ES5标准,缺省只支持原生JS函数。
1. UI/SM/MM的简介
-
UI(User Interface) : 页面上的控件,只要能放在页面展示出来的,能在设计器中可视化编辑属性的,就是UI. 如 Button 、 ImageView、 Label 等.
-
SM(Singleton Modle) : 单例的组件,主要实现对原生单例API的封装, 如 Global 、 App、 Page、 Storage 、 Device 等.这些组件在整个app中就只有一个对象.它的方法更像是我们其它语言常用的静态方法。
-
MM(Multiton Modle) : 多实例组件, 对原生的多实例API的封装. 如 SQLite 、 Http 、 Animation 等.在整个app中可以new多个对象。
我们提供了3个对应的工厂方法以获取或构建UI/SM/MM的实例.
- ui() : 通过UI对象的id来获取对象,id是一个ui对象的id属性值。这个id值由开发者来定义,可以是任何字符串
注意:ui函数只在ui.js里执行才有意义,因为ui函数的执行是需要对应的ui文件上下文的。
var button = ui("button-id");
var imageview = ui("imageview-id");
var listview = ui("listview-id1");
var label = ui("aaa");
- sm() : 通过SM组件的名称来构建对象,不过因为是单例,只有第一次调用sm函数是构建,以后再调用就是获取已经构建好的对象了
var camera = sm("do_Camera");
var app = sm("do_App");
//在整个App任何时刻任何位置打印sm对象的地址都是唯一的
print(app.getAddress());
注意:do_Page是特殊的sm对象,但是实例并不唯一,其它文档有相关介绍
-
mm() : 通过MM组件的名称,id以及作用域来创建或者获取对象。每次执行一次mm函数都会创建一个实例对象。
比较特殊的是就是可以创建一个作用域在App级别的对象,这个对象可以在App其它地方获取到整个对象。
var http1 = mm("do_Http");//缺省在当前page作用域
var httpaddress1 = http1.getAddress();
//创建一个作用域在App级别的do_Http组件的对象,它的id是http_id1,如果在这个作用域里已经有这个id的对象,则不会创建新的,而是返回已有的对象
var http2 = mm("do_Http","http_id1","app");
var httpaddress2 = http2.getAddress();// httpaddress1 != httpaddress2
var animation = mm("do_Animation","anim_id1","page");//等同于 var animation = mm("do_Animation");
var http3 = mm("do_Http","http_id1","app");
var httpaddress3 = http3.getAddress();// httpaddress2 == httpaddress3
2. 属性
UI/MM 都定义了属性. 其中ui的属性可以在设计器的可视化界面里直接修改,属性值保存在.ui文件里。
属性的访问和设置通过js代码有以下的两种访问方式:
- 以属性名访问
var button = ui("button-id"); //获取实例
var txt = buttton.text; //获取Text属性
button.text = "设置Text属性" //设置Text属性
var bgc = button.bgColor; //获取bgColor属性
button.bgColor = "#FFFFFFEE" //设置bgColor属性
- 以get/set方法访问属性
var button = ui("button-id"); //获取实例
var txt = buttton.get("text"); //获取Text属性
button.set("text", "设置Text属性") //设置Text属性
var bgc = buttton.get("bgColor"); //获取bgColor属性
button.set("bgColor", "#FFFFFFEE"); //设置bgColor属性
/*** get/set 方法可批量 获取/设置 ***/
var g = button.get(["text", "bgColor"]); // g == {text : "获取Text属性", bgColor : "#FFFFFFEE"};
button.set({text : "设置Text属性", bgColor : "#FFFFFFEE"});
MM的属性访问方式与UI完全一致.
UI类型的属性还分为二种类型,OnlyDesign和Always
- Always:表示可以通过脚本代码来设置,如上面的示例代码,也能通过设计器的属性设置界面来设置。
- OnlyDesign:表示只能通过设计器的属性设置界面来设置,不能通过代码来动态修改。
3. 方法
UI/SM/MM 都具有方法.并且,方法包含两种类型 : 同步方法/异步方法
- 同步方法:同步方法一般执行非耗时操作,立即返回执行结果.如 UI/MM 的 get/set 都属于同步方法.
var global = sm("do_Global");
global.setMemory("str0", {demo : [1,2,3,4]});
var str0 = global.getMemory("str0");
//setMemory/getMemory 执行结束立即返回结果, 都是同步方法.
//更多详见各个模块的API.
- 异步方法:异步方法一般是因为需要执行耗时操作,操作结束后会调用注册的回调函数,并将结果以回调函数的第一参数返回.异步方法的最后一个参数是一个回调函数(function);
var storage = sm("do_Storage");
storage.getFiles("data://demo/", function(data){
//data == ["aaa.txt","bbb.json", "ccc.x"];
});
//更多详见各个模块的API.
所有方法的调用都有两种调用格式
- 多参数平铺调用(以上的示例都是这样的)
- 参数哈希式(双参数式)
//假设 : 函数 Do.demo 有4个参数 a, b, c, d 和 回调 f , 并且 c, d 两个参数可选:
//0. 参数平铺:
Do.demo( a, b , c , d , f)
Do.demo( a, b , c , f)
Do.demo( a, b , f)
//1. 散列式:
Do.demo({
a : a,
b : b,
c : c,
d : d
}, f)
Do.demo({
a : a,
b : b,
c : c
}, f)
Do.demo({
a : a,
b : b
}, f)
//以App.openPage 具体说明一下
var app = sm("do_App");
do_app.openPage(
"source://view/index.ui", //要打开的页面路径
{ demo : [1,2,3,4] }, //要传递的数据
"fade", //过场动画类型
"default", //打开页面后的键盘模式
function(data ,e){
/*do something*/
});
/*****************************************************************
*以上就是全参数式, 这样的写法参数的顺序要严格按照 API 给定的顺序输入.
*如果是异步方法, 最后一个参数应是回调函数.
*****************************************************************/
//上面的例子中, 除了第一个参数( 要打开的页面路径 ) 外, 其他参数都可选.
app.openPage("source://view/index.ui", function(data){
/*do something*/
});
//上面的的例子简洁了许多. 但是如果需求是要求写入大量的参数,明显这种方式的可读性还是很差的.
//所以我们也为这样的需求量身定做了第二套调用方案:
app.openPage( {
source : "source://view/index.ui",
data : "",
animationType : "",
keyboardMode : "default"
},
function(data ,e){
/*do something*/
});
// 这种方案增强了代码的可读性,第一个参数是一个hash表, (如果是异步方法 第二个是一个回调函数)
// 注意, 回调函数不能放在第一个参数当中...
//可以根据自己的喜好和习惯自行选择.
4. 事件
UI/SM/MM 都定义了事件. 每个组件所支持的事件都在组件API上做了阐述.
比如:
do_Button : touch/touchUp/touchDown
do_Page : loaded
....
UI/SM/MM 事件的订阅/触发/注销 都是同样的规则.
- 订阅事件 [ .on() ]:订阅的事件可以是API支持的事件(touch/touchUp), 也可以是自定义的事件( touch001 / touch002 )
var button = ui("button-id");
//订阅button 的touch事件.(手指点击页面此Button时触发, 或通过fire 方法手动触发.)
button.on("touch", function(){
/*do something*/
this.bgColor = "#FF00FFFF";
// this == button;
});
//订阅button 的touch001事件.( 只能通过 fire 触发 );
buttoon.on("touch001", function(){
/*do something*/
this.bgColor = "#FF0000AA";
});
var page = sm("do_Page");
//订阅当前页面的 loaded 事件( 页面加载完成时候触发,或通过fire方法手动触发.);
page.on("loaded", function(){
/*do something*/
var data = this.getData()// this == page;
});
//订阅当前页面的 xxxxx 事件( 只能通过 fire 触发 );
page.on("xxxxx", function(data){
/*do something*/
});
//其他详见各组件的API.
- 触发已订阅的事件[ .fire() ] :如果是组件支持的事件, 组件会根据自身当前状态自动触发(Button:touch / Page:loaded ...).如果不是组件所支持的事件, 需要调用 fire 方法手动触发.
button.fire("touch");
button.fire("touch001", { demo : "手动触发touch001"});
page.fire("xxxxx", { demo : 1, demo2 : false , demo3: "xx?xx"});
//fire方法传递两个参数,第一个参数是事件名称, 第二个参数是需要传递的数据(此参数可忽略).
//事件响应时,第二个参数的值,会传递到订阅时( on方法 )的回调函数的第一个参数上.更多说明参考事件机制相关文档
- 注销已经订阅的事件[ .off() ] :调用 off方法即可
button.off("touch");
page.off("xxxxx");
5. require函数
- js版本中的require:js中的require函数的实现参照了CommonJS的风格,但是并不是完全的CommonJS Modules 的实现.
这里的详细用户可以参考文档
/******** source/script/demo.js************************************/
exports.add0 = function(a, b, c) {
return a + b + c || 0;
}
module.exports.add1 = function() {
var sum = 0, i = 0, args = arguments, l = args.length;
while (i < l) {
sum += args[i++];
}
return sum;
};
//导出了两个函数 add0 和 add1
/******* source/view/index.ui.js ************************************/
var demo = require("demo");
var t0 = demo.add0(1,2,3);
var t1 = demo.add1(1,2,3,4,5,6);
//require中的参数,就是对应的script目录下的文件名(不加.js);
网友评论