【問題摘要】怎樣經過URL來重製Flex狀態(state)?
(How do you recreate a Flex application state using an URL?) html
【解決方法】深度連接(Deep Linking)爲Flex應用程序的URL定位提供支持。 程序員
【詳細解說】 瀏覽器
什麼是深度連接(Deep Linking)?
深度連接(Deep Linking)是爲那些非Html頁面應用而給定的一種關於URL定位的描述。例如,在一個網頁裏,若是有「Home」、「About Us」和「Contact」三個導航按鈕,不管何時點擊它們,都會定向到一個獨立的URL,譬如http://riaoo.com/home.html、http://riaoo.com/contact.html。這樣的好處是,你能夠爲你感興趣的頁面添加書籤或者發給你的朋友。不然,你只能發送這個地址http://riaoo.com給你的朋友,而後告訴他如何才能進入到Contact頁面(譯者注:前者能夠一步到位到http://riaoo.com/contact.html,後者只能先進入http://riaoo.com而後再進入到Contact頁面)。
在Flex應用程序裏,當你不使用深度連接(Deep Linking)時,就像上述的第二種狀況同樣,你不能爲指定的狀態(state)添加書籤,沒有Contact頁的URL能夠發給你的好友。深度連接(Deep Linking)能夠解決這個問題而且支持瀏覽器的後退按鈕。 app
在Flex裏如何使用深度連接(Deep Linking)呢?
在Flex 3裏,爲實現深度連接(Deep Linking)功能,使用了片斷(fragments)——跟在「#」號後面的那部分。例如「http://riaoo.com/page.html#view=1」這個連接,片斷(fragments)是指「view=1」。不管你在何時爲URL添加片斷(事實上你還能夠添加任意片斷),瀏覽器都不會從新加載頁面。在Flex裏這就是你所須要的。在Flex應用程序中,你得到一個SWF文件裏的全部狀態(states),這樣你就能夠不用從新加載頁面來改變內容。
Flex使用片斷(fragments)來「存儲」狀態(state),並且當一個URL被加載時,Flex應用程序能夠分析URL上的片斷來定位到對應於URL的狀態。接下來讓咱們來看看程序員如何在一個Flex應用程序裏寫和讀URL片斷(fragments)。
BrowserManager是一個在瀏覽器與Flex應用程序之間扮演着代理角色的單例。它能使你:
■ 在當前的URL上插入片斷(fragments)
■ 設置Html頁面的title
■ 在URL改變事件中註冊事件監聽器
咱們須要使用到的第二個類是URLUtil這個靜態類,它擁有方便操做URL的方法。最後,爲了防止干涉處理片斷(fragments),咱們須要禁用HistoryManager(這個傢伙能控制Flex應用程序的後退和前進)。咱們能夠把historyManagementEnabled屬性值設爲false來禁用它(例如:<mx:Application historyManagementEnabled=」false」>)。
爲使深度連接(Deep Linking)起做用,程序員所要作的事情主要就是編寫函數來把當前狀態(state)信息連載到URL上或者把它去掉,並經過那些狀態信息來控制Flex應用程序的狀態。(原話:Most of the work a programmer does for Deep Linking is centered on creating functions that either 「serialize」 the current state to URL or 「deserialize」 the URL and use that information to change the Flex application state.) 函數
【簡單例子】 this
咱們來看看一個使用了深度連接(Deep Linking)的簡單例子。它有三個狀態(state):默認狀態、「Step 2」狀態和「Step 3」狀態。在這個Flex應用程序裏爲了代表這三種狀態,我使用了Accordion組件。其實我可使用mx:states控件、一個tabset或者其它UI組件。不過這些都沒有關係,原理是同樣的。正如我說的那樣,使用深度連接(Deep Linking)的程序員的主要任務是編寫函數來把狀態(state)信息連載到URL上或者把它去掉。而後,你須要把那些函數在Flex應用程序裏註冊爲事件監聽器。在這個例子裏,doUpdateURL()函數是用來向URL添加片斷(fragments)的,parseURL()函數是用來去掉片斷的。那個URL能夠控制Accordion組件哪項被選擇。爲了這樣,我取得當前Accordion組件的selectedIndex值並保存它做爲片斷(fragments)。例如,要經過URL來選擇Accordion組件的第二項,應該要這樣:http://riaoo.com/deep_linking_project.html#view=1,注意在尾部的「view=1」,這就是用來「存儲」selectedIndex值的片斷(fragments)了。
你應該看到了,我在mx:Application裏把historyManagementEnabled屬性值設爲false了。而後我聲明瞭三個變量:一個引用了BrowserManager、一個用來標識是否正在分析URL、最後一個是用來存儲Html頁面的title值。
我定義了一個init()函數,當Application加載完成時執行的。在這個函數裏,我初始化了BrowserManager變量,並把它做爲URL改變時的事件監聽器。最後一行調用了parseURL()函數,看註釋就好。 spa
// 引用單例的BrowserManager類 public var browserManager:IBrowserManager; // 指示是否正在分析URL private var isParsing:Boolean; // 用來存儲各個狀態(state)的title private var arrTitles:Array = ["Welcome to Flex Deep Linking Example", "Step 2", "Step 3"]; /** * 當application加載後,這個函數會被執行 * 初始化browserManager 變量併爲BROWSER_URL_CHANGE事件註冊監聽器 */ private function init():void { browserManager = BrowserManager.getInstance(); browserManager.init(「」, 「Welcome to Flex Deep Linking Example」); browserManager.addEventListener(BrowserChangeEvent.BROWSER_URL_CHANGE, parseURL); callLater(parseURL); }
/** * 一旦瀏覽器的URL被改變,這個函數就會被調用 * @參數:event */ private function parseURL(event:Event = null):void { isParsing = true; // 從當前瀏覽器的URL上找到片斷(fragments),而後把它解析爲一個對象 // 例如:若是有一個「view=1」的片斷,那麼「view」會被解析爲屬性名,「1」會被解析爲屬性值 var o:Object = URLUtil.stringToObject(browserManager.fragment); // 當沒有片斷時執行 if (o.view == undefined) o.view = 0; // 把URL上找到的片斷(fragments)值賦給Accordion組件的selectedIndex 屬性,也就是根據片斷view的值來改變Accordion組件的項 ac.selectedIndex = o.view; // 根據Accordion組件當前已被選擇的項來改變瀏覽器的title var title:String = arrTitles[o.view]; browserManager.setTitle(title); isParsing = false; }
/** * 爲Accordion組件的改變事件註冊監聽器 */ private function updateURL():void { if (!isParsing) // callLater函數延遲執行doUpdateURL()函數,是進入下一幀後才執行,就是UI被重繪後 callLater(doUpdateURL); }
/** * 這個函數修改瀏覽器的URL */ private function doUpdateURL():void { var title:String = 「」; var fragments:String = 「」; var o:Object = {}; // 當用戶選擇了Accordion組件的非第一項時 if (ac.selectedIndex > 0) o.view = ac.selectedIndex; // 爲當前選擇狀態找到對應的title title = arrTitles[ac.selectedIndex]; // 把對象解析爲片斷(fragments)字符串 fragments = URLUtil.objectToString(o); // 改變瀏覽器的title browserManager.setTitle(title); // 向瀏覽器的URL追加片斷 browserManager.setFragment(fragments); }
<mx:HBox> <mx:Accordion id="ac" change="updateURL()" width="200"> <mx:Canvas label="Step 1" width="100%" height="100%"> <mx:TextArea editable="false" text="Step 1 Accordion Content" height="300" width="100%"/> </mx:Canvas> <mx:Canvas label="Step 2" width="100%" height="100%"> <mx:TextArea editable="false" text="Step 2 Accordion Content" height="300" width="100%"/> </mx:Canvas> <mx:Canvas label="Step 3" width="100%" height="100%"> <mx:TextArea editable="false" text="Step 3 Accordion Content" height="300" width="100%"/> </mx:Canvas> </mx:Accordion> <mx:Canvas width="439" height="82"> <mx:TextArea x="19" y="10" width="410" height="62" editable="false" text="Sample Application for Deep Linking in Flex. As you change the Accordion selection the URL is updated and you can paste this URL in a new browser. The state of the application is recreated from the URL."/> </mx:Canvas> </mx:HBox>