《電子技術(shù)應(yīng)用》
您所在的位置:首頁(yè) > 通信與網(wǎng)絡(luò) > 設(shè)計(jì)應(yīng)用 > 基于Lizard框架Ctrip Wireless H5數(shù)據(jù)存儲(chǔ)方式的優(yōu)化
基于Lizard框架Ctrip Wireless H5數(shù)據(jù)存儲(chǔ)方式的優(yōu)化
2016年微型機(jī)與應(yīng)用第11期
杜燕忍,葛華勇,,王龍
(東華大學(xué) 信息科學(xué)與技術(shù)學(xué)院,,上海 201620)
摘要: Lizard是針對(duì)目前前端開(kāi)源框架中存在的不足,,由攜程研發(fā)出的適用于無(wú)線移動(dòng)端開(kāi)發(fā)的框架。Lizard Web App是運(yùn)行在瀏覽器上的單頁(yè)應(yīng)用,所有加載資源都放在一個(gè)html文件上,所有的用戶交互都交給JavaScript,,所有的通信都交給Ajax。該文基于Lizard框架實(shí)現(xiàn)Hybrid App(混合模式移動(dòng)應(yīng)用)的開(kāi)發(fā),,并針對(duì)框架中本地存儲(chǔ)方式進(jìn)行改進(jìn),,由此提出了擴(kuò)展store的存儲(chǔ)方式。以多態(tài)方式封裝store,,由LocalStorage,、IndexDB、SQLite by App替換cookie,,進(jìn)而支持多種本地存儲(chǔ)方式,,該文只是針對(duì)其中一種方式即LocalStorage進(jìn)行封裝,以提高攜程業(yè)務(wù)開(kāi)發(fā)效率,。
關(guān)鍵詞: Lizard HybridApp JavaScript WebApp
Abstract:
Key words :

  杜燕忍,,葛華勇,王龍

 ?。|華大學(xué) 信息科學(xué)與技術(shù)學(xué)院,,上海 201620)

  摘要:Lizard是針對(duì)目前前端開(kāi)源框架中存在的不足,由攜程研發(fā)出的適用于無(wú)線移動(dòng)端開(kāi)發(fā)的框架,。Lizard Web App是運(yùn)行在瀏覽器上的單頁(yè)應(yīng)用,所有加載資源都放在一個(gè)html文件上,,所有的用戶交互都交給JavaScript,,所有的通信都交給Ajax。該文基于Lizard框架實(shí)現(xiàn)Hybrid App(混合模式移動(dòng)應(yīng)用)的開(kāi)發(fā),,并針對(duì)框架中本地存儲(chǔ)方式進(jìn)行改進(jìn),,由此提出了擴(kuò)展store的存儲(chǔ)方式。以多態(tài)方式封裝store,,由LocalStorage,、IndexDB、SQLite by App替換cookie,,進(jìn)而支持多種本地存儲(chǔ)方式,,該文只是針對(duì)其中一種方式即LocalStorage進(jìn)行封裝,以提高攜程業(yè)務(wù)開(kāi)發(fā)效率,。

  關(guān)鍵詞:Lizard,;Hybrid App,;JavaScript;Web App,;HTML,;Ajax;數(shù)據(jù)存儲(chǔ)方式,;無(wú)線移動(dòng)端開(kāi)發(fā)

0引言

  近年來(lái)國(guó)內(nèi)外對(duì)Native App取得了很多重要的研究成果,,但是對(duì)Hybrid App研究還比較少?;旌夏J揭苿?dòng)應(yīng)用(Hybrid App)是指介于Web App與Native App這兩者之間的App[1],它雖然看上去是一個(gè)Native App,,但只有一個(gè)UI WebView,里面訪問(wèn)的是一個(gè)Web App,,它具有Native App良好用戶交互體驗(yàn)的優(yōu)勢(shì)和Web App[2]跨平臺(tái)開(kāi)發(fā)的優(yōu)勢(shì),。

  隨著HTML5[34]可通過(guò)手機(jī)瀏覽器運(yùn)行,而不直接依賴于手機(jī)操作系統(tǒng),,并且現(xiàn)在各大手機(jī)瀏覽器均支持HTML5[5],;Mobile phone中框架的發(fā)展(例如PhoneGap)也為Web App的發(fā)展提供了契機(jī)。主流的Hybrid方案分成三種:以PhoneGap[6]為代表,,以WebView作為用戶界面層,,以Javascript[78]作為基本邏輯,與中間件通信,,再由中間件訪問(wèn)底層API的方式進(jìn)行應(yīng)用開(kāi)發(fā),;以Titanium為代表,通過(guò)對(duì)開(kāi)發(fā)者提供友好的開(kāi)發(fā)工具,,并折中地把這種開(kāi)發(fā)語(yǔ)言轉(zhuǎn)換成原生語(yǔ)言,,最終打包出整個(gè)應(yīng)用;以Three20為代表,,在開(kāi)發(fā)原生應(yīng)用的基礎(chǔ)上,,嵌入WebView,但是整體的架構(gòu)使用原生應(yīng)用提供。在攜程無(wú)線[9]的Hybrid框架中,,一開(kāi)始就選擇了PhoneGap方案,,未來(lái)攜程App會(huì)成為一個(gè)平臺(tái)。

  本文基于Lizard框架[10]實(shí)現(xiàn)Hybrid App的開(kāi)發(fā),,針對(duì)原有框架中的本地存儲(chǔ)方式和第三方框架的引用進(jìn)行改進(jìn)和優(yōu)化,,并對(duì)改進(jìn)的方法進(jìn)行實(shí)際項(xiàng)目開(kāi)發(fā),,結(jié)果與改進(jìn)之前的結(jié)果一樣符合開(kāi)發(fā)項(xiàng)目的要求,,驗(yàn)證了本方法的有效性。

  1Ctrip Wireless H5整體架構(gòu)圖

  H5整體架構(gòu)圖如圖1所示,。由整體框架可知,,無(wú)線H5基礎(chǔ)框架主要包含以下部分,,各業(yè)務(wù)模塊需按要求對(duì)以下部分進(jìn)行統(tǒng)一引用。

001.jpg

  (1)第三方框架:zepto,、backbone,、require、understore等需要統(tǒng)一引用,。

  (2)核心框架:Common.js,,提供最基礎(chǔ)的UI、網(wǎng)絡(luò)通信(ajax),、數(shù)據(jù)存儲(chǔ)(cookie)等基類,,以及UI組件、Widget組件,、HybridAPI等組件,,需要統(tǒng)一引用。

  (3)H5公共基礎(chǔ)樣式:Main.css,,提供最基礎(chǔ)和公共樣式,,需要統(tǒng)一引用。

  (4)H5公共業(yè)務(wù)組件:各類通用的業(yè)務(wù)組件,,比如常旅客,、常用地址,需要統(tǒng)一引用,。

  (5)H5公共業(yè)務(wù)模塊攜程(登錄/注冊(cè)),、支付等業(yè)務(wù)模塊,需要統(tǒng)一引用,。

2Lizard框架

  2.1框架簡(jiǎn)介

002.jpg

  Lizard框架架構(gòu)如圖2所示,,Ctrip.H5.Lizard主要由4個(gè)模塊構(gòu)成:第三方框架、核心框架,、公共組件庫(kù),、業(yè)務(wù)組件庫(kù)。

 ?。?)第三方框架:Ctrip.H5.Lizard底層依賴的第三方庫(kù)有4個(gè):Zepto、underscore,、backbone和Fastclick,。

  在Mobile端,Ctrip.H5.Lizard會(huì)加載Zepto,,在PC端考慮到兼容性的問(wèn)題,,IE內(nèi)核瀏覽器會(huì)采用Jquery,Ctrip.H5.Lizard可以做到對(duì)環(huán)境自適應(yīng)進(jìn)行加載,。

  Backbone在Ctrip.H5.Lizard是被定制的,,其MVC框架中的Model和Controller的內(nèi)容根據(jù)Ctrip.H5.Lizard適用的環(huán)境被復(fù)寫(xiě),。

  Ctrip.H5.Lizard抽取了Fastclick的核心代碼,復(fù)寫(xiě)了移動(dòng)端的click事件,。

 ?。?)核心框架:Ctrip.H5.Lizard實(shí)現(xiàn)了Web App的基礎(chǔ)功能。

  在Javascript[1114]中實(shí)現(xiàn)了面向?qū)ο缶幊?OOP)的基礎(chǔ),,封裝了Ajax請(qǐng)求,,處理了本地環(huán)境下的跨域訪問(wèn),并對(duì)請(qǐng)求做了緩存處理,,通過(guò)監(jiān)控Hash的變化,,實(shí)現(xiàn)View的無(wú)縫切換。

 ?。?)公共組件庫(kù):Ctrip.H5.Lizard的公共組件庫(kù)涵蓋了UI組件庫(kù)和Widget組件庫(kù)兩個(gè)模塊組,。

  UI組件庫(kù)以特定的樣式表為基礎(chǔ),定制Ctrip Mobile的UI組件,,實(shí)現(xiàn)了各種交互電話,、時(shí)間選取等,Widget組件庫(kù)提供了功能性組件庫(kù)和UI業(yè)務(wù)組件庫(kù),。

 ?。?)業(yè)務(wù)組件庫(kù):Ctrip.H5.Lizard的業(yè)務(wù)組件庫(kù)主要包括攜程(登錄/注冊(cè))、支付等業(yè)務(wù),。

  2.2Lizard算法流程

003.jpg


  Lizard算法流程圖如圖3所示,,Lizard渲染數(shù)據(jù)共分成5個(gè)階段:T1~T5。T1:頁(yè)面響應(yīng)時(shí)間,。此時(shí),,用戶通過(guò)瀏覽器發(fā)起一個(gè)請(qǐng)求,當(dāng)前VIEW的HTML文件返回index.html給瀏覽器,,瀏覽器接收到index.html開(kāi)始解析,,之后瀏覽器請(qǐng)求核心框架JS處理。Lizard.js收到請(qǐng)求,,此時(shí)進(jìn)入T2階段,,即數(shù)據(jù)通信請(qǐng)求階段。Lizard.js返回核心框架中的JS文件給瀏覽器,,瀏覽器收到核心框架中JS傳來(lái)的數(shù)據(jù),,開(kāi)始解析Model Config,根據(jù)Config中的API請(qǐng)求SOA數(shù)據(jù),,SOA收到瀏覽器的數(shù)據(jù)請(qǐng)求,,此時(shí)進(jìn)入T3階段,即數(shù)據(jù)通信接收階段,。SOA返回?cái)?shù)據(jù)給瀏覽器,,瀏覽器接收到SOA的數(shù)據(jù),,此時(shí)T3階段完成,T4階段開(kāi)始,,瀏覽器根據(jù)接收到的SOA數(shù)據(jù),,開(kāi)始解析Template,此時(shí)DOM生成,,但是其為隱藏狀態(tài),,此時(shí)瀏覽器繼續(xù)發(fā)送請(qǐng)求給核心JS框架,T4階段完成,。此階段又可以稱作DOM穩(wěn)定階段,。JS中的核心框架收到瀏覽器的頁(yè)面邏輯請(qǐng)求開(kāi)始進(jìn)行處理,此時(shí)進(jìn)入T5階段,,即頁(yè)面顯示階段,。JS返回處理的結(jié)果給瀏覽器,瀏覽器收到結(jié)果顯示DOM,,展示頁(yè)面,,T5階段完成。其中T1~T4又稱作DOM準(zhǔn)備階段,,T2~T3稱為通信準(zhǔn)備階段,,整個(gè)T1~T5又叫做Onload階段。Onload是Lizard渲染頁(yè)面階段中的View生命周期的一部分,。

3Lizard Web App 中View的生命周期

  首先,,View的生命周期與攜程無(wú)線Hybrid密不可分,圖3Lizard算法架構(gòu)在一個(gè)Hybrid架構(gòu)的頁(yè)面會(huì)有兩部分組成:Head和Content,。Head是由App提供的Android/IOS原生組件,,對(duì)應(yīng)IOSNavigationBar/AndroidActionBar。Content由App提供的WebView加載H5提供的頁(yè)面,,H5與App約定將一組API綁定在WebView的Window對(duì)象中,。App通過(guò)IOS/Android原生方法調(diào)用到Window對(duì)象,執(zhí)行js的方法,,這稱之為App Native調(diào)用Web,。App實(shí)現(xiàn)對(duì)WebView URL的觀察者模式,H5通過(guò)改變URL的哈希值,,App會(huì)通過(guò)解析哈希值的變化執(zhí)行對(duì)應(yīng)的操作,,這稱之為Web調(diào)用App Native。Lizard支持Hybrid模式,,而Lizard在對(duì)Hybrid的設(shè)計(jì)中,采用了切面編程的思想,。Web與Hybrid最后的產(chǎn)品差異就在于入口文件,,在入口文件中,,會(huì)去做初始化,判斷當(dāng)前的環(huán)境,,然后以當(dāng)前環(huán)境作為參數(shù),,配置相應(yīng)的設(shè)置,切換各種服務(wù)在不同環(huán)境下的配置,。所以從開(kāi)發(fā)者的角度來(lái)說(shuō),,不用關(guān)心當(dāng)前的環(huán)境是Web還是App,只需要調(diào)用相應(yīng)的服務(wù)即可,,剩下的事情交給Lizard自身就可以,。

  其次,Lizard中頁(yè)面的整體布局代碼如下:

  define(['libs', 'cBasePageView'], function (libs, BasePageView){

  var viewhtml = '<h1>Hello World</h1>';

  var View = BasePageView.extend({

  onCreate: function () {

  this.MYMel.html(viewhtml);

  }

  onLoad: function () {

  this.turning();

  }

  onShow: function () {

  }

  onHide: function () {

  }

  });

  return View;

  });

  在該代碼中顯示了View的4個(gè)生命周期回調(diào)順序,。

  onCreate -> onLoad -> onShow -> onHide

  (1)onCreate

  onCreate是只有在view生成時(shí)才會(huì)調(diào)用的回調(diào),。在這個(gè)回調(diào)中,一般處理View的模板構(gòu)建,、初始化數(shù)據(jù)設(shè)置,。onCreate只會(huì)在初始化時(shí)候執(zhí)行一次,第二次訪問(wèn)不會(huì)執(zhí)行,。

  (2)onLoad

  onCreate每次調(diào)用View時(shí)都會(huì)首先調(diào)用的回調(diào)方法,。在該回調(diào)中需要處理數(shù)據(jù)請(qǐng)求、View的數(shù)據(jù)綁定,、渲染和View的交互邏輯設(shè)置,。onLoad的回調(diào)中需要執(zhí)行this.turning()才會(huì)宣告view的加載完成,進(jìn)入到下一個(gè)生命周期onShow,,onLoad在每次切換View時(shí)都會(huì)執(zhí)行,,一般在onload中進(jìn)行Ajax異步數(shù)據(jù)請(qǐng)求,請(qǐng)求suceess后調(diào)用turning方法從而觸發(fā)onShow事件,。

  (3)onShow

  onShow是新DOM完成渲染之后進(jìn)入頁(yè)面的回調(diào),,部分依賴頁(yè)面渲染之后的業(yè)務(wù)邏輯可以綁定在這個(gè)回調(diào)中,onShow的執(zhí)行時(shí)機(jī)為調(diào)用turning之后,,不調(diào)用turning不會(huì)執(zhí)行onShow,。

  (4)onHide

  當(dāng)頁(yè)面執(zhí)行了從A頁(yè)面跳轉(zhuǎn)到B頁(yè)面時(shí),A頁(yè)面會(huì)執(zhí)行hide方法,,將View A推到后臺(tái),。onHide就是在A推到后臺(tái)之后的回調(diào)。

4改進(jìn)數(shù)據(jù)存儲(chǔ)方式

  在一個(gè)應(yīng)用中數(shù)據(jù)的存儲(chǔ)是非常重要的功能,,在攜程的應(yīng)用場(chǎng)景中,,大量基礎(chǔ)數(shù)據(jù)會(huì)被緩存下來(lái),比如城市列表、用戶使用歷史等信息,。在Web 2.0時(shí)代,,Web存儲(chǔ)呈現(xiàn)多樣化的趨勢(shì),除了傳統(tǒng)的cookie,,HTML5提供了LocalStorage,、SessionStorage、ApplicationCache等存儲(chǔ)方案,,同時(shí)Chrome還支持IndexDB,。cookie操作在前端開(kāi)發(fā)過(guò)程中經(jīng)常遇到,當(dāng)然如果只是用來(lái)存儲(chǔ)一些簡(jiǎn)單的用戶數(shù)據(jù),,還是比較容易的,,要做的可能只是設(shè)置cookie名、值,、過(guò)期時(shí)間等,,讀取也只要根據(jù)cookie的名讀取相應(yīng)的cookie值即可。HTML5本地存儲(chǔ)的前身就是cookie,,HTML5的本地存儲(chǔ)是使用LocalStorage對(duì)象將Web數(shù)據(jù)持久化在本地,。相比較而言,HTML5本地存儲(chǔ)中每個(gè)域的存儲(chǔ)大小默認(rèn)是5 MB,,比起cookie的4 KB要大得多,。因此,HTML5本地存儲(chǔ)可以看做是加強(qiáng)版的cookie,,不受數(shù)據(jù)大小限制,,有更好的彈性以及架構(gòu),可以將數(shù)據(jù)寫(xiě)入到本機(jī)的ROM中,,還可以在關(guān)閉瀏覽器之后再次打開(kāi)時(shí)恢復(fù)數(shù)據(jù),,以減少網(wǎng)絡(luò)流量。同時(shí),,這個(gè)功能算得上是另一個(gè)方向的后臺(tái)“操作記錄”,,而不占用任何后臺(tái)資源,減輕硬件設(shè)備壓力,,增強(qiáng)運(yùn)行流暢性,,而且存儲(chǔ)和讀取數(shù)據(jù)的代碼極為簡(jiǎn)練。因此在Lizard框架中采用了LocalStorage作為解決方案,。同時(shí)參考redis在本地實(shí)現(xiàn)了小型的文檔型數(shù)據(jù)庫(kù),。

  在store中針對(duì)LocalStorage封裝了常用的方法,比如get(tag,oldFlag)獲取已存儲(chǔ)數(shù)據(jù),、getAttr(attrName,tag)獲取已存儲(chǔ)對(duì)象的屬性,、set(value,tag,{oldVal})向store中添加數(shù)據(jù),、setAttr(attrName, attrVal,tag)設(shè)置屬性值、remove()移除數(shù)據(jù)存儲(chǔ),、removeAttr(attrName)移除指定對(duì)象的存儲(chǔ)屬性,、setExpireTime(time)設(shè)置過(guò)期時(shí)間、setLifeTime(lifeTime,override)設(shè)置當(dāng)前對(duì)象的過(guò)期時(shí)間,。

  數(shù)據(jù)存儲(chǔ)的整個(gè)過(guò)程如下:

  (1)創(chuàng)建storage項(xiàng)目。

  (2)cStore模塊的引用:Lizard用cStore模塊封裝了LocalStorage的CURD操作,,所以在使用數(shù)據(jù)存儲(chǔ)時(shí),,需要引入cStore模塊。Lizard采用require.js作為模塊加載器,,所以在使用時(shí)需要顯示申明依賴關(guān)系,。引用代碼如下:

  define([libs,cBasePageView,cStore], function(libs, BasePageView, Store){ ... });這里顯示調(diào)用了cStore模塊,在回調(diào)的參數(shù)對(duì)應(yīng)的位置中給出store對(duì)象,。

  (3)Store的繼承:Lizard實(shí)現(xiàn)了Javascript的OOP開(kāi)發(fā),,為代碼的復(fù)用提供了更好的機(jī)制。在Store的一般使用中,,推薦將具體的Store繼承于cStore模塊,,代碼如下:

  var StoreCase = new Base.Class(Store, {

  __propertys__: function () {

  this.key = STORAGE_EXAMPLE //設(shè)置在LocalStorage中的key值

  this.lifeTime = 2D//D代表天,H代表小時(shí),,M代表分鐘,,S代表秒

  }

  initialize: function (MYMsuper, options) {

  MYMsuper(options);

  }

  });

  Store采用單例模式,所以需要通過(guò)StoreCase.getInstance()獲得,即var storeinstance = StoreCase.getInstance(),。

  (4)Store的增刪改讀:首先設(shè)置view模板,,其次進(jìn)行綁定操作。Store提供了3個(gè)接口做綁定操作:讀取Store.read(tag),,設(shè)置/更新Store.set({...}),,刪除Store.remove()。

  (5)設(shè)置數(shù)據(jù)的過(guò)期時(shí)間:對(duì)于過(guò)期時(shí)間的處理,,在內(nèi)部實(shí)現(xiàn)中參考redis的數(shù)據(jù)結(jié)構(gòu),,本文設(shè)置了數(shù)據(jù)的過(guò)期時(shí)間。在LocalStorage中數(shù)據(jù)結(jié)構(gòu)如下:

  "value":{

  "inputvalue":"asdfaf"

  }

  "oldvalue":{

  }

  "timeout":"2015/12/19 15:38:37",

  "savedate":"2015/12/19 15:08:37"

  通過(guò)對(duì)LocalStorage的封裝,,可以直接在開(kāi)發(fā)時(shí)通過(guò)Lizard調(diào)用,,使開(kāi)發(fā)效率更快。

5結(jié)束語(yǔ)

  基于Lizard框架的無(wú)線開(kāi)發(fā),,是針對(duì)前端開(kāi)發(fā)人員常用的一些方法,、功能、組件等進(jìn)行的一系列封裝,,提高了開(kāi)發(fā)人員的工作效率,。本文首先對(duì)Lizard框架的架構(gòu)以及工作原理進(jìn)行簡(jiǎn)單闡述,,并針對(duì)Lizard框架中本地存儲(chǔ)方式進(jìn)行了優(yōu)化,在store中封裝了對(duì)LocalStorage的讀寫(xiě),,實(shí)現(xiàn)了在Web上的本地緩存,。其次,通過(guò)對(duì)LocalStorage的封裝,,cookie與store中的LocalStorage兩種本地存儲(chǔ)方式可以同時(shí)使用,,更加方便。最后,,正如文中所提到的一樣,,存儲(chǔ)方式還有很多,諸如IndexDB,、SQLite by App等都是以后技術(shù)發(fā)展的需要,。

參考文獻(xiàn)

  [1] 萬(wàn)曉鳳,雷繼棠,易其軍,,等.基于Android智能手機(jī)平臺(tái)的AMT監(jiān)測(cè)系統(tǒng)的設(shè)計(jì)[J].電子技術(shù)應(yīng)用,2014,40(3):6870.

 ?。?] 朱華.AJAX在WEB開(kāi)發(fā)中的應(yīng)用研究[D].哈爾濱:哈爾濱工程大學(xué),2009.

  [3] 陶國(guó)榮.HTML5實(shí)戰(zhàn)[M].北京:機(jī)械工業(yè)出版社,2012.

 ?。?] cyRotel.WEB APP,HYBRID APP與NATIVE APP的設(shè)計(jì)差異[DB/OL].(2013219)[20150825].http://www.uisdc.com/webhybridnativeapp,20141202.

 ?。?] 劉艷平,俞海英.基于HTML5的Application Cache技術(shù)研究[J].微型機(jī)與應(yīng)用,2015, 34 (20):6466.

  [6] PhoneGap.API介紹[EB/OL]. (20000118)[20160105].http://www.phonegapcn.com/docs/zh/cn/.

 ?。?] NICHOLAS.JavaScript高級(jí)程序設(shè)計(jì)[M].北京:人民郵電出版社,2006.

 ?。?] 徐浩,周德華,廠卓,等.面向多終端適配的移動(dòng)中間件的設(shè)計(jì)與實(shí)現(xiàn)[J].計(jì)算機(jī)科學(xué)現(xiàn)代化,2011(9):6568.

  [9] 劉妍.無(wú)線產(chǎn)品部的無(wú)線技術(shù)標(biāo)準(zhǔn)及指南[DB/OL].(20141208)[20160105].http://conf.ctripcorp.com/display/Wireless/3.HTML5.


此內(nèi)容為AET網(wǎng)站原創(chuàng),,未經(jīng)授權(quán)禁止轉(zhuǎn)載,。