跳到主要內容

PureMVC, 快樂玩Part1

PureMVC, 快樂玩Part1
最近除了熱血的工作, 熱血的研究Progression, 當然還有熱血的PureMVC
好吧, 我承認這東西有一定的難度, 但上手後, 真的還滿方便的。
PureMVC是一種程式語言的框架, 不限於 AS3 , 官網有很多的版本可以任君選擇。
主要有三個概念
Model, Proxy
負責將數值變數存起來, 當數值被更改時, 就發送通知, 然後就什麼事也不做了。

View,Mediator
一個Mediator就對映一個View(視覺元件), 當View做了某件事情後, 發送通知。

Controller,Command
當 Mediator 被通知到後, 就執行事件做作好的Command

有了簡單概念後, 來開始試寫看看。
先下載 PureMVC AS3 standard 2.0.4版本

在這兒我們寫了一個小型的相本, 由 xml 管理, 畫面上有左、右鍵,二個動態文字
和一個要載入圖片用的Sprite。

奶小茶的習慣是先從Proxy來開始寫, 因為載入資料是最先要做的事情。
ListProxy.as
package milkmidi.puremvc.model {
import flash.events.Event;
import flash.net.URLLoader;
import flash.net.URLRequest;
import milkmidi.puremvc.model.vo.ListVO;
import org.puremvc.as3.interfaces.IProxy;
import org.puremvc.as3.patterns.proxy.Proxy;
public class ListProxy extends Proxy implements IProxy {  

public static const NAME    :String = "ListProxy"; 

//當 xml 載入完成後, 會發送notification
public static const DATA_LOAD_COMPLETE :String = 'dataLoadComplete';

//當 xml 索引值改變時
public static const MODEL_CHANGE  :String = 'modelChange';

//當 ListProxy 被設定新值時
public static const SET_CURRENT_INDEX :String = 'setCurrentIndex';  

private var _urlLdr   :URLLoader = new URLLoader();
private var _xml   :XML;
private var _currentIndex :uint = 0;
public function ListProxy(data:Object = null) {
super(NAME, data);
_urlLdr.addEventListener(Event.COMPLETE , completeHandler);
_urlLdr.load(new URLRequest('xml_data.xml'));
//載入 xml 。
}  
private function completeHandler(e:Event):void {
_xml = XML(e.currentTarget.data);
//載入完成後,將得到的 xml 設定到 data裡。
setData( _xml );
sendNotification(DATA_LOAD_COMPLETE , data);   
//記得要發通知喔。
}  
public function setCurrentIndex(pIndex:uint):void {
_currentIndex = pIndex;
//設定索引值
if (_currentIndex < 0) _currentIndex = 0;   
else if (_currentIndex >= length - 1)
_currentIndex = length - 1;
//判斷有沒有爆掉。

var _vo:ListVO = new ListVO();
_vo.img = currentImgURL;
_vo.title = currentTitle;
_vo.page = currentPage;
//將新的數值發送出去。
sendNotification(MODEL_CHANGE , _vo);   
}
public function get length():uint {    return _xml.item.length();  }
public function get currentImgURL():String { return _xml.item[currentIndex].img;  }
public function get currentTitle():String {  return _xml.item[currentIndex].title;  }
public function get currentPage():String {  return (_currentIndex + 1) +'/' + length; }    
public function get currentIndex():uint {   return _currentIndex; }


}
}
//在這兒也準備一個VO(ValueObject), 方便給大家使用。
ListVO.as
package milkmidi.puremvc.model.vo {  

public class ListVO {  
public var title:String = '';
public var img :String = '';
public var page :String = '';

public function ListVO()  {   

}  
} 
}

有了Proxy後,下一步來寫View跟Mediator
在這兒我們就只有一個主場景, 所以就準備一個ApplicationMediator.as
Mediator的工作就是觀查視覺元件的一切, 偵聽他的事件
更改他的數值, 就是他的保母啦。
package milkmidi.puremvc.view {
import flash.events.Event;
import milkmidi.puremvc.model.ListProxy;
import milkmidi.puremvc.model.vo.ListVO;
import org.puremvc.as3.interfaces.IMediator;
import org.puremvc.as3.interfaces.INotification;
import org.puremvc.as3.patterns.mediator.Mediator;
import milkmidi.puremvc.view.*;
public class ApplicationMediator extends Mediator implements IMediator { 
// Cannonical name of the Mediator
public static const NAME:String = "ApplicationMediator";  
public function ApplicationMediator(viewComponent:Object) {
super(NAME, viewComponent);
//偵聽主場景上的事件。
container.addEventListener('nextItem' , nextItemHandler);
container.addEventListener('prevItem' , prevItemHandler);
}  
private function prevItemHandler(e:Event):void {
sendNotification( ListProxy.SET_CURRENT_INDEX , -1 );   
//發送通知。
}  
private function nextItemHandler(e:Event):void {
sendNotification( ListProxy.SET_CURRENT_INDEX , 1 );
//發送通知。
}
override public function getMediatorName():String {
return ApplicationMediator.NAME;
}     
override public function listNotificationInterests():Array {
return [    
ListProxy.DATA_LOAD_COMPLETE,
ListProxy.MODEL_CHANGE
];
//我只關心這些通知, 其他沒寫的就通通不管。
}
override public function handleNotification(note:INotification):void {   
trace(facade.retrieveProxy( ListProxy.NAME));
//得到發送事件的 ListProxy 實體。
trace(note.getBody())   
//得到發送通知時, 一起帶過來的數值
switch (note.getName()) {        
case ListProxy.DATA_LOAD_COMPLETE:  
sendNotification( ListProxy.SET_CURRENT_INDEX , 0 );
break;
case ListProxy.MODEL_CHANGE:      
var _listVO:ListVO = note.getBody() as ListVO;
container.title_txt.text = _listVO.title + '';
container.numbers_txt.text = _listVO.page;
break;    
default:
break;  
}
}  
private function get container():Main {
return viewComponent as Main;
//轉型用, 給自己看的。
}
}
}
//另一個ImageContainerMediator.as ,是觀查場景上的載入圖片用的Sprite, 寫法差不多,就不多介紹了。

ApplicationFacade, PureMVC 的總代理, 在這奶小茶使用的是 Standard版
所以只會有一個Facade, 如果要多個應用程式, 多個Facade的話,可以選用 MultiCore版本。
所有的 Proxies , Mediators 跟 Commands 註冊
他的程式碼很少, 都是固定的寫法。
package milkmidi.puremvc {
import flash.display.Stage;
import org.puremvc.as3.interfaces.IFacade;
import org.puremvc.as3.patterns.facade.Facade;
import milkmidi.puremvc.model.*;
import milkmidi.puremvc.view.*;
import milkmidi.puremvc.controller.*;
public class ApplicationFacade extends Facade implements IFacade {
// Notification name constants
public static const STARTUP:String = "startup";  
public static function getInstance():ApplicationFacade {
if (instance == null) instance = new ApplicationFacade();
return instance as ApplicationFacade;
}  
// Register commands with the controller
override protected function initializeController():void {
super.initializeController();   
registerCommand(STARTUP, StartupCommand);
}
public function startup( pApp:Main ) : void {   
sendNotification( STARTUP, pApp );
//這兒是用來啟動整個 PureMVC用的
}  
} 
}

啟動用的Command
StartupCommand.as
package milkmidi.puremvc.controller { 
import milkmidi.puremvc.model.ListProxy;
import milkmidi.puremvc.view.ApplicationMediator;
import milkmidi.puremvc.view.ImageContainerMediator;
import org.puremvc.as3.interfaces.INotification;
import org.puremvc.as3.patterns.command.SimpleCommand;
public class StartupCommand extends SimpleCommand{
public function StartupCommand(){
super();
}
override public function execute(notification:INotification):void {   
var _main:Main = notification.getBody() as Main;   
facade.registerMediator( new ApplicationMediator( _main));
//注冊 Mediator
facade.registerMediator( new ImageContainerMediator( _main.container_mc));
//注冊 Mediator, 在這兒是用來載入外圖品片的容器。
facade.registerProxy( new ListProxy());   
//注冊 Proxy。
facade.registerCommand( ListProxy.SET_CURRENT_INDEX , ModelChangeCommand);   
//注冊 Command
}
}
}
//當要更改 ListProxy裡數值用的Command
package milkmidi.puremvc.controller {
import milkmidi.puremvc.model.ListProxy;
import org.puremvc.as3.interfaces.INotification;
import org.puremvc.as3.patterns.command.SimpleCommand;
import org.puremvc.as3.patterns.observer.Notification;
public class ModelChangeCommand extends SimpleCommand {

override public function execute(note:INotification):void {  
var _listProxy :ListProxy = facade.retrieveProxy( ListProxy.NAME ) as ListProxy;
var _data  :int = int(note.getBody());  
_listProxy.setCurrentIndex(_listProxy.currentIndex + _data);   
}

}
}

再來就是整個Clinet的主程式。
package  {  
import flash.display.MovieClip;
import flash.display.SimpleButton;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.text.TextField;
import milkmidi.puremvc.ApplicationFacade;  
public class Main extends Sprite {   
//場景上的元件
public var right_btn    :SimpleButton;
public var left_btn     :SimpleButton;
public var numbers_txt  :TextField;
public var title_txt    :TextField;
public var container_mc :MovieClip;  
public function Main()  { 
right_btn.addEventListener(MouseEvent.CLICK , clickHandler);
left_btn.addEventListener(MouseEvent.CLICK , clickHandler);
ApplicationFacade.getInstance().startup( this );
//啟動PureMVC。
}    
private function clickHandler(e:MouseEvent):void {   
//左、右鍵只管發送事件, 就沒啦。
if (e.currentTarget == left_btn) 
dispatchEvent(new Event('prevItem'));
else 
dispatchEvent(new Event('nextItem'));   
}
} 
}

完成啦, 搞的大家都很不熟, 這就是PureMVC的精神呀
下次在專案上實作看看。
SourceCodeDownload

留言

jerry寫道…
最近我也在用mvc,但只是將寫出來的CLASS,分成MODEL VIEW CONTROLLER,請問老師,用puermvc的特色在哪呢?
milkmidi寫道…
他將物件分的更多,
相對程式碼也會比較多
如果只是小型的應用程式
不一定要用pureMVC
不果這東西這麼紅, 一定有他的道理在
Unknown寫道…
Tweenlite是要自己下載嗎@@?
milkmidi寫道…
Sorry, 我有用TweenMax類別
到Google打,第一筆就是他的網站
Unknown寫道…
請問老師

在規劃程式的時候`,你會先在紙上做UML圖的規劃嗎?
milkmidi寫道…
不會也,我跟 UML 超不熟的
通常都以功能面來規劃
天下為公寫道…
站長問一下flash AS3要怎麼讓滑鼠的游標改變成手指啊?? 我不要一直用箭頭~~
milkmidi寫道…
只要對物件使用buttonMode=true;即可
請問一下我在試做puremvc我重新啟動了startup, sendNotification 就傳送了兩次,我該怎麼讓他只傳送一次.

這個網誌中的熱門文章

超好用的無限免費網頁空間,無廣告,無流量限制

大家好,我是奶綠茶 今天來教大家如何申請一個無限免費速度又快的網頁空間 1 首先到  https://github.com/ 申請帳號(一直下一步,下一步,下一步) 2 到你的個人頁,切換上方的 tab 到 Repositories, 按下右鍵的 new 3 Repository name 一定要是這樣的格式 username.github.io 我的 github 網址是 github.com/milkmidi 那就要輸入 milkmidi.github.io 選擇 public, 這樣別人才看的到 private 有其他用途, 而且要付費才能使用 完成後按下 Create repository 5 安裝 SourceTree github 並不支援 FTP 或是網頁上傳,一定要透過指令碼 在這我們選用有圖型介面的軟體,方便大家學習 https://www.sourcetreeapp.com/ 下載並安裝 啟動後登入你的 github 帳號 6 clone 你的 github io 專案 右上角有個 Clone or download 點選後 複製 https 連結(不要選到 ssh ) 7 將 https 的連結貼到 SourceTree 8 上傳 html 到本機 github.io 資料夾,放一個 index.html 切換到 SourceTree, 這時會看到 Unstaged files 的欄位 選擇 Stage All 9 git 要求每次的 Commit, 都一定要打說明文字(好習慣) 輸入完成後,按下右邊的 Commit 10 發佈(Push),這樣就完成啦 可以到你的 http://milkmidi.github.io/ 去查看檔案有沒有出來 其他 Commit 可以想像是做一個記錄,你可以很多的 Commit 最後再一次 Push 上去 github 原本是給程式設計師用的版本控管服務 免費版提供無限空間讓你放檔案,但一定要是 public 想要有私有的 Project ,就只能付費 github.io 只能放靜態檔案,php, aspx 服務並不支援。 祝大家學習愉快 轉載請註明出處 奶綠的 github.io S

奶綠茶新書上市_密技公怖_程式碼下載

奶綠茶第一本 Flash 書籍上市啦 博客來書籍館 Flash 3D 特效宅急便 - 商業範例隨學隨 把我對 Flash 的研究與熱愛, 全寫在其中 本書的前幾章, 特別安排 ActionScript3.0 的許多範例 好讓你一步步瞭解 as2 和 as3 的差別 再安排製作動畫不可缺少的 Tweener 類別和一些常用的數學動畫公式 最後當然就來到本書的重點 PV3D 啦 從 PV3D 的原理, 基本架構一點一點的介紹 再透過許多實用的範例, 從中瞭解 PV3D 製作的小技巧 有任何書籍相關的問題, 也請不吝指教 感謝一路走來, 幫助過我的前輩們, 邦邦、Ticore、神魂、Maso、Erin 旗標出版社 小編 Bready 米蘭數位所有夥伴 米蘭數位ActionScript Team:Jason,Ash,Mark 本書大鋼: 1.ActionScript3.0概論 分析AS3的概念與語法, 從基本的滑鼠事件、外部載入、氣泡事件介紹起 適合熟悉AS2, 想轉戰AS3的人員。 2.程式碼製作動畫 使用簡單的數學公式, 套用到程式裡, 脫離死版的影格動畫。 3.製作動畫的好夥伴:Tweener 除了套用數學公式外, Tweener類別也能加速我們開發出更多的動畫效果, 不需辛辛苦苦的找公式。 4.自定類別 AS3的精神, 是在於強大的物件導向, 當然也要熟悉類別的寫法與使用。 5.Flash3D - Papervison3D 如果在Flash玩轉3D效果, PV3D是最好學, 最快上手的3D Flash Engine, 從簡單的3D概念, PV3D類別, 事件等。 6 漫天飛舞的Paper3DWorld效果 7 迷你旋轉木馬式秀圖效果 8 最經典! CoverFlow 圖像展示效果 9 天旋地轉 TiltViewer效果 10 FlatWall3D電視牆效果 11 經典旋轉木馬 Carousel3D 秀圖效果 12 光源材質展示與簡易型的方塊彈跳效果 13 載入外部3D模型與動畫 14 超立體旋轉九宮格 Box3DWorld 15 空間感與透明感兼具的 SpaceGallery 16 螺旋式 SpiralCarouse 影像展示 17 Flash10 3D功能 18 Flash效

奶綠茶photoGalleryV3.5

奶小茶的photoGalleryV3.5原始檔 2007/12/30 更新小Bug,請重新下載 線上Demo: http://milkmidi.com/photogallery/galleryv3.html 1.支援SWFAddress,讓FLASH可以有上一頁下一頁和每張獨立網址的功能 2.圖片路徑圖說經由XML來設定 3.背景依據顯示圖片,自動變化成最接近的顏色 4.非商業用途,歡迎使用並修改(如果覺得我製作的好,也煩請加入我的logo) 5.可結合後端伺服器 00.art 相本集資料夾 com 奶綠茶的Class檔 swfaddress SWFAddress資料夾 swfobject swfobject資料夾 XML galleryV3.fla 原始檔 index.html 主檔html SWFAddress.as SWFaddressEvent.as Source Code Download 解壓密碼:回覆文章,即可看見Password