分享人:夏燕飛
近期因為需求與bug比較多,因此有些拖更了。非常抱歉,那么今天的干貨開始了。。。
該篇為“快應用”第一篇。歡迎大家閱讀!


自快應用問世,到現在也已經有一年多了。快應用和微信小程序類似。都是用戶體驗介於網頁與原生APP之間的新型應用模式。微信小程序我想大家都用過,但是快應用卻不一定。首先微信小程序問世要比快應用早一年,而且靠着微信的用戶社交粘性和閉環,以及小程序支持安卓與ios端。使得小程序到目前為止,依舊發展得比快應用好。但未來不一定。


快應用可以說是9大手機廠商為了不使微信小程序搶占應用流量而出現的吧。
畢竟微信小程序是以微信為載體,是一種二級應用,打開小程序前必須要打開微信的占用內存。而快應用是手機廠商出品的,不需要以某個為載體,直接操作系統打開,屬於一級應用。可以直接調用底層系統功能。其實廠商可根據其優勢,提升手機的原生性能,使得其強於微信小程序的體驗也是可以的,不過這得待后期發展了。
現在我們從技術角度來說說開發快應用吧!


項目結構
按快應用腳手架工具初始化的項目基本能滿足一般的項目開發需求了。比如現在初始化一個
hap init hiquick
項目:
得到一個如下結構的項目目錄:
├── sign //rpk包簽名模塊
├── src
│ ├── Common //公用的資源和組件文件
│ ├── Demo //頁面目錄
│ │ └── index.ux //頁面文件,可自定義頁面名稱
│ ├── app.ux //APP文件,可引入公共腳本,暴露公共數據和方法等
│ └── manifest.json //項目配置文件,配置應用圖標、頁面路由等
其中 Demo 目錄即是一個頁面目錄,包含一個 ux 后綴的頁面文件。項目構建運行之后,還會產生 build/、dist/ 兩個目錄。build 是打包構建后生成的 js 文件、dist 則是 rpk 安裝包。
在我們實際項目中由於業務比較復雜,會創建很多頁面,這樣平鋪在根目錄下,造成文件夾過多不易管理維護。
於是我們新建一個文件夾 pages 專門存放頁面,這樣項目結構就變成了:
├── sign
├── src
│ ├── common //公用資源、全局配置
│ ├── components //公用組件
│ ├── pages
│ │ ├── index //頁面目錄
│ │ │ └── index.ux //頁面文件
│ │ └── login
│ ├── app.ux
改造后的目錄結構更直觀、簡潔。不過要記得去修改默認的頁面路由配置:router.pages、display.pages 兩項的頁面鍵值要改和頁面路徑一致。如這里首頁的配置就是 pages/index。
除了新增 pages 目錄,還新增了 components 文件夾和更改 common 文件夾的用途。
新增的 components 文件夾專門存放公用的組件文件,而 common 則專門用來存放公共資源、工具方法和全局配置等文件。這樣使得目錄的功能區分更明白了,也為后面的代碼復用作好了基礎准備。
其中全局配置的配置項皆以模塊化輸出,既對變量有一個統一的維護管理,也方便在業務直接引入調用,一舉兩得,非常高效。


頁面划分
上面已經說了我們為所有頁面專門建立了一個 pages 文件夾。從中可以看出應用中的所有頁面是平級划分的。雖然在業務邏輯上可能存在父子關系,但實際頁面沒必要分出從屬,那樣只會增加頁面關系的復雜度。
但這里有一個特殊頁面還是設計了父子關系。這么做也恰恰想表明頁面間從屬關系。這就是 pages/index 頁面,為了避免概念混淆,這里先稱之為索引頁。因為它正是起着索引導航作用的,並不是常規意義上的首頁。
通常,一個APP的界面是這樣的:

在界面底部會有一個導航菜單欄,叫做 TabBar,然而快應用並沒有這種組件。雖然利用頁面路由可以做導航,但效果並不理想,切換過來的頁面都需要重新加載。由於頁面中已經使用了 tabs 組件,使用tabs組件實現也不可行。
剩下就需要自己動手打造了。既要實現頁面導航,又要實現頁面緩存的功能。
簡要分析下組件的設計思路。
在單頁內實現不同頁面的切換,功能相當於一個Tab。
功能區分為tab標簽欄和tab內容區。
標簽的項目不能寫死,要可以自由擴展。
每個標簽對應的頁面以組件形式引入。
在 index.ux 頁面需要引入 TabBar 頁面組件。作為子組件,為方便管理,我們把這些子頁面組件作為子文件夾放在 index/ 下管理維護,一目了然地表明頁面的從屬關系,整體項目的頁面切分工作也完成了。
│ ├── pages
│ │ ├── index //索引導航目錄
│ │ │ ├── subpages //子頁面目錄
│ │ │ │ ├── featured //子頁面
│ │ │ │ │ └── index.ux //子頁面組件文件
│ │ │ │ └── member
│ │ │ │ └── index.ux
上面 TabBar 的功能設計還忽略一點,就是子頁面組件更新的問題。為此做了監聽標簽切換及頁面 onShow 事件觸發組件更新的處理,這里不做詳細說明。


公共代碼
下面着重來說下公共代碼部分,公共代碼及組件化向來都是項目中的重點部分,這部分作好了,會使得項目代碼越寫越少,越寫越高率。相反,如果這部分沒有做好,不僅會讓項目代碼變得一團糟,不斷地重復工作,還極有可能會埋下一些潛在的危險。
比如項目中公用的一個參數,分別寫在各個地方,等到需要更改時,很可能改了一個地方而忘了另一個地方,等到出錯還不容易排查問題出在哪里。如果統一在一處配置好,其它所有地方只引入這個配置,則會從根本上規避這個低級錯誤。
當然這只是做好公共管理的優點之一。
公共代碼和組件化開發應該深入到任何項目的任何角落,應該時刻保持這種意識。
在快應用項目中我們將公共資源、公共代碼都放在了 common 文件夾下。包含全局基礎樣式文件、圖片資源、配置項文件、和工具方法。
配置項文件 config.js 集中管理全局使用的常量和API接口地址,並對依賴不同域名環境下的配置項做自動切換處理。
工具方法 utils.js 將可復用的工具函數方法抽象出來,並以模塊化形式導出,方便其它模塊中按需引入,而不需要在不同的地方重復地寫同一個工具方法了。
再來說說組件化,這也是項目開發中的重點。
組件化應該是在項目一開始就需要着手考慮的事情,原則上在交互稿評審階段就需要開始了。分析出哪些部件可以提取抽象出公共組件。這樣多人協作的項目中,共同開發將變得非常有效率。
快應用項目目前拆分出的公共組件有圖文展示組件、TitleBar頁面標題欄組件、錯誤狀態提示組件、章節目錄組件等(排除快應用框架自身的組件)。
TitleBar組件實現自定義的頭部標題樣式,在默認的標題欄不滿足需求時可以使用該組件實現。
錯誤狀態提示也是復用較高的組件,在處理無網絡、暫無數據等狀態下都可以直接引用。大大減少代碼的重復開發工作。


體驗、性能的優化
除了以上的改造優化外,性能的優化也是無法繞開的。開發過程中除了基本該做的優化要做到之外,能發現的性能問題也應該尋找方案解決。當然如果時間不允許或者暫無方案解決則另當別論。
那快應用項目中所做的性能優化工作列舉幾點如下。
TabBar頁面導航優化
前面說了TabBar的設計思路,也提到了設計的意義,涉及的主要優化有:
按需加載,首次只加載默認標簽頁。
頁面緩存,避免切換時頁面的重復加載。
返回鍵退出應用,避免路由鏈路過長。
TabBar配置的標簽項,默認只會加載其中一個頁面,這個初始展示的頁面由配置項 currentTabName 決定。點擊其它標簽后,才加載對應的頁面。頁面加載完成后,再次切換標簽,已加載的頁面則是顯示或隱藏,不會重新加載渲染。提高了用戶使用體驗的同時,也節約了沒必要的網絡請求。
前面也提到直接使用路由跳轉也是可以實現類似的效果。使用路由來實現,技術復雜度會大大降低,但使用感受也比較糟糕。除了切換時頁面重復加載渲染之外 ,頁面棧也會隨着不斷切換而加大,這時如果想返回則會走很長的鏈接。雖然可以通過設置replace路由替換規避,但頁面重復加載渲染是避免不了的。
快應用與web組件的通信優化
快應用的訂購環節由於技術限制,需要引用web組件來加載HTML頁面實現訂購。交易環節事關重大,功能上容不得半點差錯,性能上要保證穩定可靠。技術上涉及到快應用與HTML之間的通信。而在調試過程中卻發現了通信機制的一個Bug。
起始在開發中發現web組件存在通信不穩定的問題,初步判定為可能頁面還未加載完成。為保證通信的可靠性,我們在頁面加載完成的回調事件 onpagefinish 中發起通信。然而web組件會自動觸發兩次 onpagefinish 回調。原因暫時不明確,問題也和官方溝通過。總之這會造成HTML中監聽通信的請求也發送兩次。於是想辦法去阻止web組件二次觸發回調事件。
在 onpagefinish 事件中設置回調狀態,如果判斷狀態為true 則表明web已經完成加載,就不用再次發起通信。這樣處理之后,發現不會再二次觸發了,而且在調試和測試過程中觀察通信成功率達到100%。


總結
項目技術選型、架構設計及優化工作都是開發過程的重要因素。一個合理的項目架構會讓開發過程變得省力有趣。相反則會低效,既影響開發體驗也對優化及后續維護、優化不利。
如果各位對我們有什么意見或建議,歡迎回復我們哦。
覺得不錯的童鞋們請記得點贊、轉發、關注三連哦!!!
從現在起我們的公眾號已改名為“大前端早讀”內容范圍圍繞大前端,也開啟系列篇,更多原創文章請關注我們,
並點擊內容系列--原創篇,學習更多:
