AppWorker教程-数据绑定

数据绑定

数据绑定是在应用程序 UI 与数据源建立连接的过程。如果绑定正确数据,则当数据更改其值时,绑定到数据的UI属性值会自动反映更改。AppWorker支持灵活的数据绑定,使UI展示和数据可以清晰的分离。目前还不支持双向绑定,只支持数据到展示的传递。
使用AppWorker开发App,你可以不使用任何数据bind机制,传统的获取对象,给对象每一个单个属性设置值也可以实现所有功能。但是使用bind机制可以减少代码,优化框架,使开发工作事半功倍。

1.基本绑定方式:

bind包括源和目标,AppWorker的bind目标通常指UI组件,所有的UI组件都支持基本的bind方式。实际上只要一个组件有属性就可以支持bind,比如UI和MM(MultitonModule)组件都有属性,都支持bind。

bind的源我们目前提供了2个组件do_ListDatado_HashData分别表示二种数据结构,hash和array,因为整个AppWorker的数据基础都是json格式,所以这2个数据组件都是只能处理json格式。
UI和MM类的基类都提供了3个相关的方法来实现bind机制。

  • setMapping方法:设置一个UI组件或者MM组件的属性和数据的映射关系。
  • bindData方法:设置UI组件或者MM组件的数据源,这个数据源目前只能是do_ListDatado_HashData.
  • refreshData方法:当bind的数据源数据发生变化后,调用这个方法来刷新数据源的展示。
    示例如下:
function test1() {
        // 创建一个HashData对象
        var data = mm("do_HashData");
        // 给Button创建一个属性到数据的映射,其中text和bgColor是Button的2个属性
        btn1.setMapping({
                "text" : "text_key",
                "bgColor" : "color_key"
        });
        // 建立Button和HashData的绑定
        btn1.bindData(data);
        // 数据变化驱动UI属性变化
        // 1. 修改数据
        data.addData({
                "text_key" : "映射到HashData",
                "color_key" : "FF0022AA"
        });
        // 2. 刷新UI,这个按钮的文本变成“映射到HashData”,背景颜色变为“FF0022AA"
        btn1.refreshData();
}

其中一个UI的映射可以作为bindData的一个参数,比如

function test2() {
        // 创建一个HashData对象
        var data = mm("do_HashData");
        // 建立Button和HashData的绑定,同时设置映射关系
        btn2.bindData(data, {
                "text" : "text_key",
                "bgColor" : "color_key"
        });
        // 数据变化驱动UI属性变化
        // 1. 修改数据
        data.addData({
                "text_key" : "映射到HashData-直接设置映射",
                "color_key" : "FFCC00AA"
        });
        // 2. 刷新UI,这个按钮的文本变成“映射到HashData-直接设置映射”,背景颜色变为“FFCC00AA"
        btn2.refreshData();
}
// ...

其中HashData对象支持path,中间用.号来隔开,比如

function test3() {
        // 创建一个HashData对象
        var data = mm("do_HashData");
        // 给Button创建一个属性到数据的映射,其中text和bgColor是Button的2个属性
        // HashData对象支持path,中间用.号来隔开
        btn3.setMapping({
                "text" : "node1.text_key",
                "bgColor" : "node1.color_key"
        });
        // 建立Button和HashData的绑定
        btn3.bindData(data);
        // 数据变化驱动UI属性变化
        // 1. 修改数据
        data.addData({
                "node1" : {
                        "text_key" : "映射到HashData-支持path",
                        "color_key" : "F00FEEAA"
                },
                "node2" : "xxxx"
        });
        // 2. 刷新UI,这个按钮的文本变成“映射到HashData-支持path”,背景颜色变为“F00FEEAA"
        btn3.refreshData();
}

其中数据源也支持ListData,中间用:加数字索引来表明是一个list的一个元素

function test4() {
        // 创建一个HashData对象
        var data = mm("do_HashData");
        // 给Button创建一个属性到数据的映射,其中text和bgColor是Button的2个属性
        // HashData对象支持json array,中间用:加数字索引来表明是一个array的一个元素
        btn4.setMapping({
                "text" : "node1:2.text_key",
                "bgColor" : "node1:2.color_key"
        });
        // 建立Button和HashData的绑定
        btn4.bindData(data);
        // 数据变化驱动UI属性变化
        // 1. 修改数据
        data.addData({
                "node1" : [ {
                        "text_key" : "我是Button1",
                        "color_key" : "FFFFEEAA"
                }, {
                        "text_key" : "我是Button2",
                        "color_key" : "FFFFEEBB"
                }, {
                        "text_key" : "映射到HashData-支持JSONArray",
                        "color_key" : "00FFEECC"
                } ],
                "node2" : "xxxx"
        });
        // 2. 刷新UI,这个按钮的文本变成“映射到HashData-支持JSONArray”,背景颜色变为“00FFEECC"
        btn4.refreshData();
}

function test5() {
        // 创建一个ListData对象
        var data = mm("do_ListData");
        // 给Button创建一个属性到数据的映射,其中text和bgColor是Button的2个属性
        // do_ListData对象支持:加数字索引来表明是一个array的一个元素
        btn5.setMapping({
                "text" : ":2.text_key",
                "bgColor" : ":2.color_key"
        });
        // 建立Button和HashData的绑定
        btn5.bindData(data);
        // 数据变化驱动UI属性变化
        // 1. 修改数据
        data.addData([ {
                "text_key" : "我是Button1",
                "color_key" : "FFFFEEAA"
        }, {
                "text_key" : "我是Button2",
                "color_key" : "FFFFEEBB"
        }, {
                "text_key" : "映射到ListData",
                "color_key" : "0FF11ECC"
        } ]);
        // 2. 刷新UI,这个按钮的文本变成“映射到HashData-支持JSONArray”,背景颜色变为“00F11ECC"
        btn5.refreshData();
}

其中bind目标UI也支持path,中间用.隔开,只不过有一个限制就是这个时候的绑定目标UI必须是这个ui文件的根节点。这种情况应用更灵活方便,不需要为每一个UI创建一个映射和一个数据源,这个ui文件里所有UI组件可以共用一个映射和数据源。比如

function test6() {
        // 根据统配符$来获取ui文件的根节点,也可以根据它的ID获取对象
        var rootview = ui("$");
        // 创建一个HashData对象
        var data = mm("do_HashData");
        // 给rootview创建多个子UI的属性到数据的映射,其中button_id1.text和label_id1.text
        // 分别表示这个ui文件里一个id为button_id1的Button组件和id为label_id1的Label组件
        rootview.setMapping({
                "do_Button_6.text" : "node1.text_key",
                "do_Button_7.text" : "node2",
                "do_Button_6.bgColor" : "node1.color_key",
                "do_Button_7.bgColor" : "node3"
        });
        // 建立Button和HashData的绑定
        rootview.bindData(data);
        // 数据变化驱动UI属性变化
        // 1. 修改数据
        data.addData({
                "node1" : {
                        "text_key" : "多个子UI绑定1",
                        "color_key" : "1FFFE1BB"
                },
                "node2" : "多个子UI绑定2",
                "node3" : "1111FFBB"
        });
        // 2. 刷新UI,二个按钮的文本变成“多个子UI绑定1,2”,背景颜色变为“1F1F1EBB,11111EBB"
        rootview.refreshData();
}

2.特殊绑定方式:

这种bind机制不是所有UI组件都具有的,只有类似ListView,GridView等组件才有,这种组件的共性在于用户看到的视图是有限的,但是实际上通过手势滑动可以有很多个数量不定的视图。这种bind有以下几个概念:

  • templates:模板是这种类型组件的一个属性,里面包含的是ui文件名。不管这种View有多少个子视图,但是模板数量是固定的,比如大部分ListView有很多个单元,但是这些单元都是共用一个或几个模板,只不过每一个单元对应的数据不一样。
  • bindItems:这个是这种类型组件的一个方法,这个方法的参数只能是do_ListData,表明这个视图和一个list数据结构的数组对象绑定在一起。
  • refreshItems:类似UI基类的refreshData方法,这个方法是这种类型组件的一个方法。当bind的ListData发生变化后,通过这个方法来刷新界面。

以下是一个ListView的示例代码,这里面的代码实际上是写在不同的2个ui文件对应的ui.js文件里,比如ListView所在的文件叫listview_sample.ui.js

// listview_sample.ui.js文件
// 建立绑定.....
// 1. 根据ListView的ID获取一个ListView的对象
var listview = ui("listview_id1");
// 2. 设置ListView的模板,这里只设置了一个模板文件,其实有可能有多个。
//这个示例中,假设这个模板文件里面只有一个id为button_id1的Button组件
//在ui文件里设置listview的templates属性为"source://listview_cell.ui"
//也可能支持多模板比如templates属性为"source://listview_cell1.ui,source://listview_cell2.ui"
// 3. 创建一个ListData对象
var data = mm("do_ListData");
// 4. 建立ListView和ListData的绑定
listview.bindItems(data);

// 数据变化驱动UI属性变化
// 1. 修改数据
data.addData([{"text_key":"我是Button1","color_key":"#FFFFEEAA"},
              {"text_key":"我是Button2","color_key":"#FFFFEEBB"},
              {"text_key":"我是Button3","color_key":"#FFFFEECC"},
              {"text_key":"我是Button4","color_key":"#FFFFEEDD"},
              {"text_key":"我是Button5","color_key":"#FFFFEEEE"},
             ]);
// 2. 刷新UI,这个ListView会增加6个子视图,每个视图里的按钮的文本变成“我是Button”+n,
//背景颜色变为“FFFFEE"+XX
listview.refreshItems();

以上的例子想要运行成功,还需要在listview_cell.ui对应的listview_cell.ui.js文件里添加以下类似代码

//listview_cell.ui.js文件
// 建立绑定.....
// 1. 根据统配符$来获取ui文件的根节点,也可以根据它的ID获取对象
var rootview = ui("$");
// 2. 给rootview创建子UI的属性到数据的映射,其中button_id1.text和button_id1.bgColor
//表示这个ui文件里有一个id为button_id1的Button组件
rootview.setMapping({"button_id1.text":"text_key","button_id1.bgColor":"color_key"});
//注意这里不需要再单独bind一个数据源了,这个文件作为listview的模板文件,会自动和listview绑定的数据建立bind关系。
//listview绑定的数组数据中每一项元素都是这个模板文件的数据源。

ListView用的很广,示例也非常多,参考示例大全
注意:当组件绑定多个模板时,数据内需要多加一个key为“template”,指定单条数据绑定的模板索引,默认从0开始

3.dataRefreshed 事件:

这个事件也很重要,通常一个UI对象和一个Hashdata建立映射关系之后,当hashdata更新数据后,UI对象调用refreshData或refreshItems后,UI对象会接受到数据,然后更新对应的属性值,之后会触发这个事件。
这个事件会通常可以用在Listview,Gridview,Slideview这种UI组件,它们都包含多个ui文件,都有模板ui文件。通过这个事件可以实现主ui和模板ui的数据通讯。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,539评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,911评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,337评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,723评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,795评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,762评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,742评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,508评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,954评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,247评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,404评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,104评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,736评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,352评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,557评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,371评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,292评论 2 352

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 172,035评论 25 707
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,649评论 18 139
  • 1、通过CocoaPods安装项目名称项目信息 AFNetworking网络请求组件 FMDB本地数据库组件 SD...
    阳明先生_X自主阅读 15,979评论 3 119
  • 2018年1月1日,天气晴。 我们在油画村相遇和重逢。 潘潘从福建来广东参加传统文化的学习,在大芬油画村与她重逢。...
    雅_ef0e阅读 401评论 2 3
  • 《迷雾》:开挂的人生不需要解释,做好自己就行 最近热播的一部韩剧《迷雾Misty》可谓是刷爆了朋友圈,剧情紧...
    睿心Lady阅读 674评论 -1 3