深入了解 Dojo 的数据访问和绑定工具包

本文首发于:http://www.ibm.com/developerworks/cn/web/1203_zhouxiang_dojoxwire/


作为 Dojo 这样一个强大且全面的 web 开发控件库中的一部分,它提供了很多简单且功能完善的 API。通过这些 API,我们能够很方便的实现数据的绑定,包括简单数据的绑定、复杂数据的绑定、绑定转换器、动作或者事件的绑定以及各种数据绑定适配器,如:文本型适配器、表格型适配器、树型适配器等等。它不仅支持脚本类型的接口 API:“dojox.wire.ml”,还支持声明式的 API,即:以 Dojo 的 Widget 的方式直接在 HTML 中声明来进行数据绑定的操作。这篇文章将重点介绍 Dojo 的这种数据访问和绑定的功能,以及我们如何基于 Dojo 的 Wire 工具包实现自己的数据访问和绑定。

Dojox 的 Wire 工具包简介

Dojox 的 Wire 工具包是 Dojo 中用于数据操作的一组工具集合,它主要用于数据绑定和服务调用。它提供了一组非常强大的 API 让用户能十分方便地访问、更新复杂数据以及向后台服务传值和取值。它也提供了一组声明式绑定数据用法,用于完善先前的只支持编程方式 API 的不足。

回页首

Dojox 的 Wire 工具包的基础接口

我们先来看看 Wire 包里面的 create 接口:


清单 1. 接口“dojox.wire.create”

                                    

 var wire = dojox.wire.create({});

 t.assertTrue(wire instanceof dojox.wire.Wire);

 

 wire = dojox.wire.create({property: "a"});

 t.assertTrue(wire instanceof dojox.wire.Wire);

 

 wire = dojox.wire.create({attribute: "a"});

 t.assertTrue(wire instanceof dojox.wire.DataWire);

 

 wire = dojox.wire.create({path: "a"});

 t.assertTrue(wire instanceof dojox.wire.XmlWire);

 

 wire = dojox.wire.create({children: "a"});

 t.assertTrue(wire instanceof dojox.wire.CompositeWire);

 

 wire = dojox.wire.create({columns: "a"});

 t.assertTrue(wire instanceof dojox.wire.TableAdapter);

 

 wire = dojox.wire.create({nodes: "a"});

 t.assertTrue(wire instanceof dojox.wire.TreeAdapter);

 

 wire = dojox.wire.create({segments: "a"});

 t.assertTrue(wire instanceof dojox.wire.TextAdapter);

 

 wire = dojox.wire.create({wireClass: "dojox.wire.DataWire"});

 t.assertTrue(wire instanceof dojox.wire.DataWire);



可见,通过 Create 接口,我们可以创建出我们所需要的相应 Wire 对象。通过以上实例,我们可以了解一下 Dojo 所支持的所有类型的 Wire 对象:Wire、DataWire、XmlWire、CompositeWire、TableAdapter、TreeAdapter、TextAdapter、DataWire。我们会在接下来的章节中一一介绍这些对象的用途,用法和使用技巧。

接下来我们再来看看另一个基础接口“transfer”:


清单 2. 接口transfer

                                    

 var source = {a: "A"};

 var target = {};

 dojox.wire.transfer(

 {object: source, property: "a"},

 {object: target, property: "a"});

 t.assertEqual(source.a, target.a);



这里的 transfer 接口其实起到了一个数据复制的作用,即将“source”的属性“a”的值复制到“target”的属性“a”上。

再来看看“connect”接口:


清单 3. 接口connect

                                    

 var trigger = {transfer: function() {}, transferArgument: function() {}};

 var source = {a: "A"};

 var target = {};

 dojox.wire.connect({scope: trigger, event: "transfer"},

 {object: source, property: "a"},

 {object: target, property: "a"});

 trigger.transfer();

 t.assertEqual(source.a, target.a);



其实“connect”的接口功能与“transfer”基本一样,但是,它是更深层次的数据复制,它定义了触发这个数据复制行为的方法,即:只有调用该方法才会触发数据复制的行为。这里的“trigger”对象的“transfer”方法就是这种方法。

还可以通过注册 topic 的方式来使用 connect 接口:


清单 4. 接口connect 基于 topic

                                    

 target = {};

 dojox.wire.connect({topic: "transfer"},

 {object: source, property: "a"},

 {object: target, property: "a"});

 dojo.publish("transfer");

 t.assertEqual(source.a, target.a);



可以看到,这里可以基于 Dojo 的 publish 方法来使用 connect 接口。

还有,connect 接口还支持参数传递:


清单 5. 接口connect 使用参数

                                    

 target = {};

 dojox.wire.connect({scope: trigger, event: "transferArgument"},

 {property: "[0].a"},

 {object: target, property: "a"});

 trigger.transferArgument(source);

 t.assertEqual(source.a, target.a);

 

 target = {};

 dojox.wire.connect({topic: "transferArgument"},

 {property: "[0].a"},

 {object: target, property: "a"});

 dojo.publish("transferArgument", [source]);

 t.assertEqual(source.a, target.a);



可见,不论是基于对象方法的 connect 接口,还是基于 topic 的 connect 接口,都可以传递参数。这里的“[0]”便是指代的第一个传入参数。

另外,如果需要取消这种关联,使用“disconnect”接口即可:


清单 6. 接口disconnect

                                    

 dojox.wire.disconnect(connection)

 

回页首

Wire 工具进阶

这一章我们主要来介绍一下稍微复杂一点的 Wire 接口,Dojo 主要将其封装在“dojox.wire.Wire”这个对象里。


清单 7. 数据的关联 Wire

                                    

 var source = {a: "A", b: {c: "B.C"}};

 var sourceWire = new dojox.wire.Wire({object: source, property: "a"});

 

 source.a = "B";

 t.assertEqual("B", sourceWire.getValue());

 

 sourceWire.setValue("C");

 t.assertEqual("C", source.a);



可以看到,“sourceWire”这个对象就像一根电线一样,连接着“source”对象的“a”属性,随时可以取得和设置该属性的值:“sourceWire.getValue()”和“sourceWire.setValue()”。这种功能很适合用于复杂的对象,我们不用每次都深入该复杂对象的内部,去访问或修改其内部某个属性的值,而只需要建立一个外部变量与该内部属性的关联(就好象牵了一根线锁定了该属性)就可以了,以后对该属性的所有操作都可以通过这个外部变量来完成。

再来看看稍微复杂一点的例子:


清单 8. 复杂数据关联 Wire

                                    

 target = {};

 value = new dojox.wire.Wire({object: source, property: "b.c"}).getValue();

 new dojox.wire.Wire({object: target, property: "b.c"}).setValue(value);

 t.assertEqual(source.b.c, target.b.c);

 

 source = {a: ["A"]};

 target = {};

 value = new dojox.wire.Wire({object: source, property: "a[0]"}).getValue();

 new dojox.wire.Wire({object: target, property: "a[0]"}).setValue(value);

 t.assertEqual(source.a[0], target.a[0]);



这里我们主要想说明的是,关联的属性值可以是 2 级甚至更多(“b.c”或“b.c.d.e.x.x.x.x.x”),同时,对于数组类型的属性值,同样可以关联(dojox.wire.Wire({object: source, property:"a[0]"}))。

再来看一组更为新颖的例子:


清单 9. 复杂数据关联 Wire 基于函数

                                    

 // by getter/setter

 source = {getA: function() { return this._a; }, _a: "A"};

 target = {setA: function(a) { this._a = a; }};

 value = new dojox.wire.Wire({object: source, property: "a"}).getValue();

 new dojox.wire.Wire({object: target, property: "a"}).setValue(value);

 t.assertEqual(source._a, target._a);

 

 // by get/setPropertyValue

 source = {getPropertyValue: function(p) { return this["_" + p]; }, _a: "A"};

 target = {setPropertyValue: function(p, v) { this["_" + p] = v; }};

 value = new dojox.wire.Wire({object: source, property: "a"}).getValue();

 new dojox.wire.Wire({object: target, property: "a"}).setValue(value);

 t.assertEqual(source._a, target._a);



从例子中可以看出,这里不论是 source 还是 target 都没有属性“a”,取而代之的是属性“_a”。但是这里我们关联的属性还是“a”,因为“setA”和“getA”方法的存在。同样,“getPropertyValue”,“setPropertyValue”也有同样的功能。所以这里我们可以看出,数据的关联还可以通过方法来完成,这种方式也会促使我们的代码变得更加规范。

让我们再深入一点,其实 Dojo 的 wire 还支持直接的类型转换:


清单 10. 复杂数据关联 Wire 类型转换

                                    

 //例 1

 var source = {a: "1"};

 var string = new dojox.wire.Wire({object: source, property: "a"}).getValue();

 t.assertEqual("11", string + 1);

 var number = new dojox.wire.Wire(

   {object: source, property: "a", type: "number"}).getValue();

 t.assertEqual(2, number + 1);

 

 //例 2

 var source = {a: "1"};

 var conv

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值