- 浏览: 85260 次
- 性别:
- 来自: 北京
最新评论
-
A5121612886:
好文要顶!
Flash Builder 编译器选项 -
谁在哀伤望月:
非常好,谢谢分享
Flash builder4 插件终极破解方法
原文地址:
http://superwulei.iteye.com/blog/484462
pureMVC简单示例及其原理讲解(用户的添加与删除)
——开篇
pureMVC是一个MVC框架,皆在最大限度的减少MVC间的耦合性。本人刚刚接触pureMVC时感到一头雾水,不知从何入手,也不知道从何学习。好在本人有耐性且能看懂英文技术文档,面向对象的编程能力也比较扎实。在这种背景下,终于悟出了pureMVC的原理,能够使用pureMVC进行开发。如果把pureMVC的领悟境界分为若干,我是处于最低境界(潜力很大啊)。好,闲话不说,言归正传。
本示例是在理解了官方示例EmployeeAdmin示例的基础之上的简化版,用意是为了更好的理解pureMVC。
界面:图片上部控件用于添加用户,下部控件用户显示用户信息和删除已添加的用户
【图1】
首先:
pureMVC既然是MVC(Model、View、Controller)框架,那你就必须要记住pureMVC中的四个主要结构类:
- Proxy(相当于Model)
- Mediator(相当于View)
- Command(相当于Controller)
- Facade(管理Proxy、Mediator和Command的东西)
也许上面小括号中的话说的不严谨,在本示例中MVC是这样划分的:
- Model:由VO(Value Object,即值对象)和Proxy组成;
- Mediator:由图1中的两个MXML文件及其对应的Mediator组成;
- Command:由一个MacroCommand和若干个SimpleCommand组成;
- Facade:即ApplicationFacade;
- 启动页:MyPureMVCDemo.mxml文件。
整个示例由以上五个部分组成。具体如图2所示。
【图2】
这里关于3和4要做一下解释。pureMVC中的Command分为两种:多命令和单一命令,即MacroCommand和SimpleCommand。MacroCommand中通过addSubCommand(SimpleCommandName)来加入子命令,两个Command中的方法都需要被重写override,此外还需要通过facade.registerCommand(...)注册命令。也许这段话我说的不清楚,你只要记住pureMVC框架包含这五个部分就可以了,咱们往下看吧!
pureMVC简单示例及其原理讲解
——Model层
pureMVC是一个MVC框架,皆在最大限度保持Model、View、Controller的独立性,从而减少各个层间的耦合。
上一篇《pureMVC简单示例及其原理讲解——开篇 》中讲述了本示例宗旨、主要功能文件结构,此外还介绍了pureMVC包含的核心组成。
回顾:
- 本示例的宗旨:本示例是在官方EmployeeAdmin示例上的简化,目的是更简单、更清楚的阐述pureMVC的原理。
- 主要功能:用户的添加和删除。
- 文件结构:http://dl.iteye.com/upload/picture/pic/46563/4dc24cc0-42d5-3e88-8d78-ea2011513dca.png
- pureMVC的核心组成:Proxy、Mediator、Command( MacroCommand & SimpleCommand )、Facade。
本节将讲述Model层。
Model层有VO和Mediator组成,非常简单,仅仅包含两个类:UserVO和UserProxy。
UserVO中的构造器用于初始化用户的添加(通过email和密码),另一个isValid属性验证用户电子邮件是否合法以及密码长度。
/** UserVO 作者:吴磊 */ package com.superwulei.model.vo { public class UserVO { public var email:String = ''; //电子邮件 public var password:String = ''; //密码 public var regDate:Date; //注册日期 public function UserVO(email:String, password:String) { this.email = email; this.password = password; this.regDate = new Date(); } /* 验证用户信息 email:以单词字符开始,以.cn结尾 password: 长度大于等于6位 */ public function get isValid():Boolean { var emailRegExp:RegExp = /^\w+[@]\w+(.com)$/; return (emailRegExp.test(this.email) && this.password.length >= 6); } } }
UserProxy代码如下。UserProxy继承Proxy。在Proxy中有一个类型为Object的data私有变量,这样就可以使用这个Object的变量存储任何数据。在UserProxy构造方法中,我们通过super方法调用父类构造器并将Object的data转换为ArraryCollect类型。由于data是私有了,因此我们通过getter返回属性的公有方法返回"ArrayCollection"类型的data。同时定义两个其他的方法用于向这个users属性中添加、删除对象。其实大家现在应该可以看出来了,这个users属性存在的目的其实就是为了存储UserVO对象。
package com.superwulei.model { import com.superwulei.model.vo.UserVO; import mx.collections.ArrayCollection; import org.puremvc.as3.patterns.proxy.Proxy; public class UserProxy extends Proxy { public static const NAME:String = 'UserProxy'; public function UserProxy() { super(NAME,new ArrayCollection()); } public function get users():ArrayCollection{ return data as ArrayCollection; } /* 添加项 */ public function addItem(item:Object):void{ users.addItem(item); } /* 删除项 */ public function deleteItem(item:Object):void{ var user:UserVO = item as UserVO; for(var i:int = 0; i < users.length; i++){ if(users[i].email == user.email){ users.removeItemAt(i); } } } } }
Model层非常简单,pureMVC设计的追求同样如此,Model层应该是稳定的、不会由于其他层的变化而变化。
本节中讲解了Model层,关键的一点是Proxy中的data,非常重要,很有意义。
pureMVC简单示例及其原理讲解
——View层
pureMVC是一个MVC框架,目的是为了将Model、View、Controller严格的划分出来。pureMVC可以用户Java、C#、ActionScript等多种编程语言。
上一篇《pureMVC简单示例及其原理讲解——Model层 》中我们讲解了Model层,非常简单。包含一个UserVO和一个UserProxy,只要记住Proxy中的data的含义就OK了。
本篇说的是View层,即视图层,在本示例中包括两个部分:MXML文件,即可视控件;Mediator。
可视控件
可视控件由UserForm.mxml(图1)和UserList.mxml(图2)两个文件组成。UserForm.mxml用于添加用户,UserList.mxml显示用户和删除已添加用户。
【图1】
【图2】
先看UserForm.mxml,既然要添加用户,就一定会要一个方法。你还记得么,在上一篇《pureMVC简单示例及其原理讲解——Model层 》中我们提到的UserProxy中有一个ArrayCollection类型的users属性和无返回值的addItem方法,其中users中存储UserVO,addItem方法用来向users中添加UserVO。现在我们既然要在界面通过添加按钮添加用户,我们必然要用到这个方法,但是我们不会在View层直接使用这个方法。因为pureMVC的追求是将MVC分离,而这些逻辑操作我们都会将其放入Command中,即Controller才层。但是在View层,我们也不是没有作为的。我先调一调你的胃口,不要着急,这个作为我们会在本篇接下来的部分讲。先看看userForm.mxml的代码。
<?xml version="1.0" encoding="utf-8"?> <mx:Panel title="Registor" xmlns:mx="http://www.adobe.com/2006/mxml"> <mx:Metadata> [Event('add')] </mx:Metadata> <mx:Script> <![CDATA[ import mx.controls.Alert; import com.superwulei.model.vo.UserVO; public static const USER_ADD:String = "add"; public var user:UserVO; /* 添加用户 */ private function addUser():void { user = new UserVO(email.text, password.text); dispatchEvent(new Event(USER_ADD)); } private function enableSubmit(u:String, p:String):Boolean { return u != '' && p != ''; } ]]> </mx:Script> <mx:Form> <mx:FormItem label="email" required="true"> <mx:TextInput id="email"/> </mx:FormItem> <mx:FormItem label="password" required="true"> <mx:TextInput id="password" displayAsPassword="true"/> </mx:FormItem> </mx:Form> <mx:ControlBar horizontalAlign="right"> <mx:Button id="sbumitButton" label="添加" enabled="{enableSubmit(email.text,password.text)}" click="addUser();"/> </mx:ControlBar> </mx:Panel>
在UserForm.mxml中定义一个Event,并对应的定义一个USER_ADD常量。来看看点击添加按钮后会怎么样?找到submitButton按钮的click事件对应的方法addUser。在addUser方法中,首先要生成一个UserVO对象user,这个user存储的信息就是你在界面上输入的email和密码;此外还要注意,这个UserVO的对象user事先已经声明,且是public的访问修饰符。之所以将user的访问限制设定为公有的,是由于这个user会在其他地方用到,这个其他地方请您关注。
一般的,一个可视控件会对应一个Mediator;但有时候多个可视控件也会对应一个Mediator。本示例中,可视控件和Mediator的关系是前者,即一对一。来看看UserForm.mxml对应的UserFormMediator.as代码。
package com.superwulei.view { import com.superwulei.ApplicationFacade; import com.superwulei.view.components.UserForm; import flash.events.Event; import org.puremvc.as3.patterns.mediator.Mediator; public class UserFormMediator extends Mediator { public static const NAME:String = "UserFormMediator"; public function UserFormMediator(viewComponent:Object) { super(NAME, viewComponent); userForm.addEventListener(UserForm.USER_ADD,onAdd); } private function get userForm():UserForm{ return viewComponent as UserForm; } /* 添加用户监听器 */ private function onAdd(event:Event):void{ add(); } /* 添加用户方法 */ private function add():void{ sendNotification(ApplicationFacade.USER_ADDED,userForm.user); } } }
在View层,Mediator是pureMVC的核心,其私有变量viewComponent表示一个可视控件,上例中viewComponent表示UserForm,通过userForm属性实现。
看构造器UserFromMediator(...)。首先调用了父类的构造方法;然后给userForm属性加上onAdd监听器,这个userFrom属性是通过getter方法实现的,见get userForm():UserForm。来看onAdd监听器,调用add方法,在add方法中使用了sendNotification方法。刚才我们所说的添加用户的方法不是没有作为,这就是我所谓的有所作为,即“发送通知”。pureMVC中将逻辑控制放在了Controller层,因此在View层就不会有添加用户的代码,但是我们将“添加用户”这个命令以通知的方式发送出去。注意sendNotification方法中携带了两个参数,第一个参数是一个常量,第二个参数是一个UserVO对象。这个常量表示会调用与之对应的Command,这个UserVO对象表示的就是要添加的用户。这个在Controller层会讲到。
UserList.mxml和UserListMediator.as和上面的道理是类似的,在此不多言。以下是UserList.mxml和UserListMediator.as的代码。
<?xml version="1.0" encoding="utf-8"?> <mx:Panel xmlns:mx="http://www.adobe.com/2006/mxml" title="已注册用户"> <mx:Metadata> [Event('delete')] </mx:Metadata> <mx:DataGrid id="userGrid" dataProvider="{users}"> <mx:Script> <![CDATA[ import mx.formatters.DateFormatter; import com.superwulei.model.vo.UserVO; import mx.collections.ArrayCollection; public static const USER_DELETE:String = "delete"; [Bindable] public var users:ArrayCollection; public var selectUser:UserVO; private function deleteUser():void{ selectUser = userGrid.selectedItem as UserVO; dispatchEvent(new Event(USER_DELETE)); } ]]> </mx:Script> <mx:columns> <mx:DataGridColumn dataField="email"/> <mx:DataGridColumn dataField="password"/> <mx:DataGridColumn dataField="regDate" width="200"/> </mx:columns> </mx:DataGrid> <mx:HBox textAlign="center"> <mx:Button id="deleteButton" label="删除" click="deleteUser();"/> </mx:HBox> </mx:Panel>
package com.superwulei.view { import com.superwulei.ApplicationFacade; import com.superwulei.model.UserProxy; import com.superwulei.view.components.UserList; import flash.events.Event; import org.puremvc.as3.patterns.mediator.Mediator; public class UserListMediator extends Mediator { private var userProxy:UserProxy; public static const NAME:String = "UserListMediator"; public function UserListMediator(viewComponent:Object) { super(NAME, viewComponent); userList.addEventListener(UserList.USER_DELETE,onDelete); userProxy = facade.retrieveProxy(UserProxy.NAME) as UserProxy; userList.users = userProxy.users; } private function get userList():UserList{ return viewComponent as UserList; } /* 删除用户监听器 */ private function onDelete(event:Event):void{ deleteUser(); } /*删除用户方法*/ private function deleteUser():void{ sendNotification(ApplicationFacade.USER_DELETE,userList.selectUser); } } }
关于Mediator再补充一下,在每个Mediator中会看到有一个公有的静态的常量字符串,这个字符串用来表示Mediator的类名。同样的在Proxy和Command中你也会看到,这样就可以通过facade的retrieveMediator、retrieveProxy和retieveCommand来检索对象。
关于Model层要记住:一个MXML可视控件对应一个Mediator,Mediator本身不处理操作但它会发送Notification(发送出去的Notification会自动被执行),关于界面上的操作采用监听的方式即addEventLisentner。
pureMVC简单示例及其原理讲解
——Controller层
pureMVC由Proxy、Mediator、Command(SimpleCommand/MacroCommand)和Facade组成。
上一节讲述了示例的Model层,Model层由可视控件和Mediator组成,Mediator本身不控制各种操作,但是会将操作以通知的方式发送出去。本节将讲述pureMVC示例中的Controller层。
Controller层有以下文件组成:
- AddUserCommand.as
- DeleteUserCommand.as
- ModelPrepCommand.as
- ViewPrepCommand.as
- StartupCommand.as
AddUserCommand 。顾名思义,它是添加用户命令。让我们首先看看代码。
package com.superwulei.controller { import com.superwulei.model.UserProxy; import com.superwulei.model.vo.UserVO; import mx.controls.Alert; import org.puremvc.as3.interfaces.INotification; import org.puremvc.as3.patterns.command.SimpleCommand; public class AddUserCommand extends SimpleCommand { override public function execute(notification:INotification):void { var user:UserVO = notification.getBody() as UserVO; var userProxy:UserProxy = facade.retrieveProxy(UserProxy.NAME) as UserProxy; if(user.isValid){ userProxy.addItem(user); }else{ Alert.show("请检查用户名和密码"); } } } }
AddUserCommand是一个单一命令(SimpleCommand),自定义SimpleCommand必须继承SimpleCommand并重写execute方法。execute方法表示这个命令的执行。曾经在上一篇《pureMVC简单示例及其原理讲解——View层 》中提到的添加用户的逻辑代码,应该在这里编写。还记得上一篇中提到的“View层本身不处理各种操作,但是发送通知”么?
拿出这段代码是特意的想说明AddUserCommand的execute方法中的notification.getBody()其实就是userForm.user,严谨的说应该是userFrom.user作为参数传到execute方法中来。如此我们在这里通过userProxy.addItem(user)就实现了用户的添加。userProxy中的users就多了一个user。
DeleteUserCommand ,删除用户命令。代码如下,与添加用户道理一样,不多言。
package com.superwulei.controller { import com.superwulei.model.UserProxy; import com.superwulei.model.vo.UserVO; import org.puremvc.as3.interfaces.INotification; import org.puremvc.as3.patterns.command.SimpleCommand; public class DeleteUserCommand extends SimpleCommand { override public function execute(notification:INotification):void { var user:UserVO = notification.getBody() as UserVO; var userProxy:UserProxy = facade.retrieveProxy(UserProxy.NAME) as UserProxy; userProxy.deleteItem(user); } } }
ModelPrepCommand、ViewPrepCommand分别是Model层注册和View层注册。说道注册就要道一道。在pureMVC中,一切总控制是facade,因此无论是Proxy、Mediator还是Command都要在facade中注册。上面四个Command全部为SimpleCommand,最后一个StartupCommand为MacroCommand(复合命令)。StartupCommand包含了多个SimpleCommand,通过addSubCommand方法添加了子命令,并在之后在facade上注册了AddUserCommand和DeleteUserCommand。
package com.superwulei.controller { import com.superwulei.model.UserProxy; import org.puremvc.as3.interfaces.INotification; import org.puremvc.as3.patterns.command.SimpleCommand; public class ModelPrepCommand extends SimpleCommand { override public function execute(notification:INotification):void { /* 注册Model */ facade.registerProxy(new UserProxy()); } } }
package com.superwulei.controller { import com.superwulei.view.UserFormMediator; import com.superwulei.view.UserListMediator; import org.puremvc.as3.interfaces.INotification; import org.puremvc.as3.patterns.command.SimpleCommand; public class ViewPrepCommand extends SimpleCommand { override public function execute(notification:INotification):void { var app:MyPureMVCdemo = notification.getBody() as MyPureMVCdemo; /* 注册View */ facade.registerMediator(new UserFormMediator(app.userForm)); facade.registerMediator(new UserListMediator(app.userList)); } } }
package com.superwulei.controller { import com.superwulei.ApplicationFacade; import org.puremvc.as3.patterns.command.MacroCommand; public class StartupCommand extends MacroCommand { override protected function initializeMacroCommand():void{ addSubCommand(ModelPrepCommand); addSubCommand(ViewPrepCommand); /* 注册添加、删除用户命令 */ facade.registerCommand(ApplicationFacade.USER_ADD,AddUserCommand); facade.registerCommand(ApplicationFacade.USER_DELETE,DeleteUserCommand); } } }
通过使用facade的registerCommand就好象添加一个监听器一样,当有sendNotification发送出来的时候,就会有对应的Command的execute方法被执行。
Controller层包含的应该是整个应用程序的逻辑业务。
pureMVC简单示例及其原理讲解
——Facade
pureMVC是一个MVC框架,核心部分包括Proxy、Mediator、Command和Facade,Facade同意管理前三个核心部分。
上一篇我们讲解了本示例中的Controller层,Controller层中包含添加用户命令、删除用户命令、注册View层的命令、注册Model层的命令和一个复合命令注册所有的这些和添加/删除用户命令。至此为止,我们讲解了pureMVC示例的MVC三层,但是整个应用程序目前仍然无法启动,正确运行。不要着急,看完本节,程序就可以运行了。
本节将讲述Facade,Proxy、Mediator、Command的统一管家。自定义Facade必须继承Facade,在本示例中自定义Facade名称为ApplicationFacade,这个名称也是pureMVC组织建议的名称。先看代码:
package com.superwulei { import com.superwulei.controller.StartupCommand; import org.puremvc.as3.patterns.facade.Facade; public class ApplicationFacade extends Facade { public static const STARTUP:String = "startup"; public static const USER_ADD:String = "user_added"; public static const USER_DELETE:String = "user_delete"; public static function getInstance():ApplicationFacade { if (instance == null) instance = new ApplicationFacade(); return instance as ApplicationFacade; } public function startup(app:Object):void { sendNotification(STARTUP, app); } override protected function initializeController():void { super.initializeController(); registerCommand(STARTUP, StartupCommand); } } }
ApplicationFacade中使用了单例模式,即整个应用程序中只会存在一个ApplicationFacade的对象。不清楚单例模式的朋友们可以通过静态方法getInstance中的代码思考一下,是不是这样。方法initializeController被重写,首先调用父类的initializeController方法,然后注册StartupCommand命令。还记得在上一章《pureMVC简单示例及其原理讲解——Controller 》中提到的StartupCommand么?它是一个复合命令,在这里注册了这个命令,其他的包括所有的Proxy、Mediator和AddUserCommand、DeleteUserCommand也会被同时注册。看一个startup方法,有一个Object类型的参数app,app接受的将是程序运行的类,没有它程序可以被加载但无法执行任何操作(这个方法具体细节本人有待研究,也欢迎广大朋友告之)。
主程序启动文件MyPureMVCdemo.mxml 代码
<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:components="com.superwulei.view.components.*" creationComplete="facade.startup(this);"> <mx:Script> <![CDATA[ import com.superwulei.ApplicationFacade; private var facade:ApplicationFacade = ApplicationFacade.getInstance(); ]]> </mx:Script> <components:UserForm id="userForm" /> <components:UserList id="userList" /> </mx:Application>
干净多了吧?在应用程序的creationComplete事件中加入facade.startup(this)的调用,其中this就表示的是当前启动类。这样一切就会通过facade走了。
- pureMVCsimple1.zip (31.7 KB)
- 下载次数: 16
发表评论
-
全面提升你的程序效率 之细说 bitmapdata AS3 Bitmap 抠图(透明部分)和碰撞(点击)检测
2012-06-05 09:54 7181如果你是刚接触as编程 ... -
PureMVC MultiCore报错 multitonKey for this Notifier not yet initialized!
2012-05-23 16:08 997multitonKey for this Notifier n ... -
关于优化
2012-05-21 14:58 9821. Avoid the new operator whe ... -
AS3经验之谈
2012-05-11 10:56 1102【改变输出swf的尺度,背景颜色 ... -
Flex 应用内存泄露的分析与诊断
2012-05-03 11:32 710http://www.ibm.com/developerwor ... -
Flash Builder 编译器选项
2012-05-02 10:30 6393-benchmark 输出性 ... -
【AS3】为什么AS3.0事件流机制会有捕获阶段、目标阶段、冒泡阶段三个阶段
2012-04-26 10:03 3830原问题:事件机制有三个步骤,捕获,目标和冒泡。请问,在目标阶段 ... -
[AS3]事件流那点事儿
2012-04-26 09:36 1238在群里有人问了个问 ... -
Socket+AMF3粘包问题
2012-04-17 10:05 1817问题: 服务端Mina 前台接收Flex 参照的 ... -
flash中cacheAsBitmap的使用
2012-03-09 11:59 818缓存显示对象 如果 Flash 中的设计尺寸增大,无论创建 ... -
Flash builder4 插件终极破解方法
2011-06-20 11:30 16081. 下载并安装FlashBuilder_4_LS10.exe ... -
泡妞与23种设计模式(转)
2011-05-26 09:41 6801、FACTORY—追MM少不了请 ... -
业务逻辑
2011-03-28 10:55 749业务逻辑是相对于展示逻辑来说的,主要用在MVC模式中。 ... -
[转]看看你是不是合格的ASer
2011-03-24 10:24 591来自 http://hi.baidu.com/onli ... -
webkit/opera中window[name]获取flash对象的特殊实现
2011-03-23 20:01 825为了兼容多数浏览器,我们一般同时采用object和embed标 ... -
10条Flash AS3开发人员实用的简单细节事情
2011-03-23 16:19 7881. 弹性“跑道“模型 开发者应该知道事件何时被触发,代码何 ... -
AS3 Flex的一个贝塞尔(Bezier)曲线图形实例
2011-03-23 16:08 1745代码如下: CurveDemo.as p ... -
[转]访问flash中的各种元素
2011-03-23 15:50 883From:http://www.xncat.com/2009/ ... -
面向接口编程详解
2011-03-22 10:23 665我想,对于各位使用面向对象编程语言的程序员来说,“接口”这 ...
相关推荐
用PureMvc开发Air项目,完整工程实例。 学PureMvc的第一个完整例子
flex PureMVC框架实例 flex PureMVC框架
按照puremvc官方网站教程做的登陆实例,在flexBuilder3上运行过.绝对好用. 供大家学习参考.
本例子运用PureMVC框架编写的简单例子,初学者可以通过本例子理解PureMVC的实现过程,各层的主要职责及如何通信.
如你下载后的存放的目录是D组:/下载,解压后将创建一个名为PureMVC_AS3_2_0_4的文件夹(注:其中的2_0_4是版本号) ; 打开PureMVC_AS3_2_0_4文件夹,您会发现里面有三个文件夹: asdoc :对应于API的文档,它的首页...
公司内部培训文档,关于pureMVC架构的详细讲解,对于软件架构设计有一定指导意义。
PureMVC五子棋游戏源码,学习PureMVC
压缩包里面有一个用puremvc制作的as实例,另附上一个puremvc的中文文档供大家参考。
PureMVC教程,是学习PureMVC框架的好文章,PureMVC教程,是学习PureMVC框架的好文章,PureMVC教程,是学习PureMVC框架的好文章PureMVC教程,是学习PureMVC框架的好文章,PureMVC教程,是学习PureMVC框架的好文章,PureMVC...
puremvc 框架源码及教程, 附带一个使用示例 puremvc 框架源码及教程, 附带一个使用示例
简单spring4 MVC简单示例,适合初学者学习!
puremvc 讲解puremvc的源码
这个是一个根据AS3(ActionScript 3) pureMVC而转换过来的lua pureMVC。所有的接口完全跟AS3版本一致。 若是想使用,可以直接查看网上的pureMVC 文档,我并未对任何一个函数改名或者更换参数位置。 注意,这个PureMVC...
基于Unity3D讲解PureMVC框架,通过游戏制作讲解,适合学习框架的人
这是一个使用C#开发语言的基于PureMVC框架的Web登录Demo,是网上绝无仅有的实例。 本文以初学者的视角,详细地介绍PureMVC在ASP.NET的应用。 PureMVC不仅仅是Flex的MVC框架哦,而且它非常的小巧,还等什么呢,快来...
这是一个MVC例子,简单的接受了MVC的实现过程。
pureMVC项目包 导入的包 pureMVC项目包pureMVC项目包
pureMVC框架 pureMVC源码 学习pureMVC的知识
PureMVC学习资料与案例PureMVC学习资料与案例PureMVC学习资料与案例PureMVC学习资料与案例