如何在不依赖Flex框架的情况下实现简单的数据绑定

问题

在Flex项目中,数据绑定是非常常见的代码编写方式,通过这种方式,我们可以减轻很多繁琐的数据更新工作,并解除一些不必要的耦合。如果你还不了解绑定,点击这里查看关于Flex中绑定的视频

如果我们是一个纯ActionScript或Flash项目,不想依赖体积大的Flex框架,而又想使用其中的绑定机制,该如何做呢?我们可以遵循绑定的思路,自己编写代码实现绑定的方法。这里以简单的字符串绑定为例,说明这个过程,当然要完整的实现对所有数据类型的绑定机制还是要编写更多的代码的,请参照Flex中对于绑定的实现。

解答

首先来看一下这个例子最终完成的Demo演示:

下面来看看是如何实现这套机制的,首先我们来创建一个可绑定的数据类,并实现对绑定对象的数据更新,注意主要是要用bind和unlock两个方法来实现对数据的绑定和解除绑定:

  1. package
  2. {
  3. public class BindableObject
  4. {
  5. public var bindProperty:*;
  6.  
  7. public function BindableObject(value:* = null):void {
  8. bindProperty = value;
  9. }
  10.  
  11. public function set property(p:*):void{
  12. bindProperty = p;
  13. BindManager.refresh(this);
  14. }
  15. public function get property():*{
  16. return bindProperty;
  17. }
  18.  
  19. public function bind(obj:*,property:String):void {
  20. BindManager.registBindableObject(obj,property,this);
  21. }
  22.  
  23. public function unlock(obj:*,property:String):void {
  24. BindManager.unlockBindableObject(obj,property,this);
  25. }
  26.  
  27. }
  28. }

其中对绑定的数据更新要依赖一个manager类来实现,参见下面的代码:

  1. package
  2. {
  3. import flash.utils.Dictionary;
  4.  
  5. public class BindManager
  6. {
  7. public static var valueDic:Dictionary = new Dictionary();
  8.  
  9. public static function registBindableObject(obj:*,property:String,value:BindableObject):void {
  10. if(value.property!=null) obj[property] = value.property;
  11. if(valueDic[value] == null) {
  12. valueDic[value] = [];
  13. }
  14. valueDic[value].push(new InnerBindableObject(obj,property));
  15. }
  16.  
  17. public static function unlockBindableObject(obj:*,property:String,value:BindableObject):void {
  18. if(value != null) {
  19. var needCheckObjs:Array = valueDic[value];
  20. for each(var item:InnerBindableObject in needCheckObjs) {
  21. if(obj == item.obj && property == item.property) {
  22. var index:int = needCheckObjs.indexOf(item);
  23. if(index!=-1) needCheckObjs.splice(index,1);
  24. }
  25. }
  26. }
  27. }
  28.  
  29. public static function refresh(value:BindableObject = null):void {
  30. if(value != null) {
  31. var needRefObjs:Array = valueDic[value];
  32. for each(var item:InnerBindableObject in needRefObjs) {
  33. if(item.obj != null) {
  34. item.obj[item.property] = value.property;
  35. }
  36. }
  37. }
  38. }
  39. }
  40.  
  41. }
  42. class InnerBindableObject {
  43. public function InnerBindableObject(o:*,p:String):void {
  44. obj = o;
  45. property = p;
  46. }
  47. public var obj:*;
  48. public var property:String;
  49. }

使用方法:

1.首先创建一个BindableObject

2.调取它的bind方法,绑定到要更新的对象,比如:bindExpObj.bind(main.txt1,"text");

3.在需要的时候,对数据源更新,比如:bindExpObj.property = main.stringSRC.text;

4.解除绑定,使用unlock方法,参数与bind相同,比如:bindExpObj.unlock(main.txt1,"text");

完整的示例代码如下:

  1. package
  2. {
  3.  
  4. import flash.display.Sprite;
  5. import flash.events.Event;
  6. import flash.events.MouseEvent;
  7.  
  8. [SWF(width=400, height=400, frameRate=25,backgroundColor=0xFFFFFF)]
  9. public class AS3TestBind extends Sprite
  10. {
  11. private var main:MainContainer = new MainContainer();
  12. private var bindExpObj:BindableObject = new BindableObject("");
  13. private var cb:NeoComboBox = new NeoComboBox();
  14.  
  15. public function AS3TestBind()
  16. {
  17. super();
  18. cb.selected = true;
  19. cb.y = 10;
  20. cb.x = 320;
  21. cb.addEventListener(MouseEvent.CLICK,unlockBind);
  22. main.stringSRC.addEventListener(Event.CHANGE,dataChange);
  23. bindExpObj.bind(main.txt1,"text");
  24. bindExpObj.bind(main.txt2,"text");
  25. bindExpObj.bind(main.txt3,"text");
  26. bindExpObj.bind(main.mc.txt,"text");
  27. addChild(main);
  28. main.addChild(cb);
  29. }
  30.  
  31. private function dataChange(...args):void {
  32. bindExpObj.property = main.stringSRC.text;
  33. }
  34.  
  35. private function unlockBind(...args):void {
  36. if(cb.selected == true) {
  37. bindExpObj.unlock(main.txt1,"text");
  38. bindExpObj.unlock(main.txt2,"text");
  39. bindExpObj.unlock(main.txt3,"text");
  40. bindExpObj.unlock(main.mc.txt,"text");
  41. cb.selected = false;
  42. cb.tip.visible = false;
  43. } else {
  44. bindExpObj.bind(main.txt1,"text");
  45. bindExpObj.bind(main.txt2,"text");
  46. bindExpObj.bind(main.txt3,"text");
  47. bindExpObj.bind(main.mc.txt,"text");
  48. cb.selected = true;
  49. cb.tip.visible = true;
  50. }
  51. }
  52.  
  53. }
  54. }

您给予的分值: None 平均分: 9 ( 7 票)

就此,我也希望aiameeting

就此,我也希望aiameeting这样一个技术比较深的网站不要轻易发表一些人云亦云没有验证考核的资料.谢谢.

非常抱歉,这个主题

非常抱歉,这个主题的初衷只是初步探索一下绑定机制,离完整可用的程度还差的很远,作者也意识到了评论中大家论及的问题,也请大家注意这不是一个最终版的解决方案,实际上要实现绑定机制远不是这样就可以解决的

flex是多层绑定. 楼主

flex是多层绑定.

楼主的这种绑定方法,其实更深一点的我也设计过,不是很满足需求,flex的正好.并且楼主跟我遇到了同样的问题,字典数组在proxy类里是无效的,所以这个类在设计期是有一定问题的.

可以使用对象的

可以使用对象的

简单的文本处理这种

简单的文本处理这种方式比较合适,但是如果是复杂对象的变化,感觉就有些力不从心了,对象的值更新了,但是和对象相关联的现实就无法实现更新。 灵活一点还是发送自定义事件,这样接收到值后也能够随心所欲的对显示进行更新。

发表新评论

  • 网页地址和电子邮件地址将会被自动转换为链接。
  • 行和段被自动切分。
  • 您可以使用下面的标签来高亮显示您的评论内容: <code>, <blockcode>. 可以使用"[foo]".旁边显示标签样式 "<foo>" PHP代码可以用这样的区块来包含<?php ... ?> or <% ... %>

更多格式化选项信息

验证区域
系统验证:请回答下面的问题