前言 在JSBridge實現後,前端網頁與原生的交互已經通了,接下來就要開始規劃API,明確需要提供哪一些功能來供前端調用。 但是在這之前,還有一點重要工作需要做: __明確H5與Native的職責劃分,確定哪一些功能可以由H5實現,哪一些功能只能由原生實現__ Native與H5職責劃分 使用Hy ...
前言
在JSBridge實現後,前端網頁與原生的交互已經通了,接下來就要開始規劃API,明確需要提供哪一些功能來供前端調用。
但是在這之前,還有一點重要工作需要做:
明確H5與Native的職責劃分,確定哪一些功能可以由H5實現,哪一些功能只能由原生實現
Native與H5職責劃分
使用Hybrid模式,用H5開發頁面的本質是:
減少工作量(一套代碼,多個平臺),以及快速的更新迭代(譬如線上更新),而且還需要考慮Native端的高性能以及系統API調用能力(否則直接用純H5就可以了)
因此在進行職責劃分時,就得充分的考慮前端渲染,JS語言以及原生渲染,Java/OC等語言的特性,基本總結如下:
混合頁面導航欄組件由原生實現
一些重要的業務頁面、帶有複雜動畫或交互的頁面以及一些固定頁面由原生實現
系統級UI由原生統一實現
頁面切換的轉場由原生實現
CPU密集型任務、底層的優化要由原生完成
其它功能能用H5實現(並且效果不錯)的就儘量不要用原生
導航欄組件由Native實現
嘗試過,也對比過很多的混合開發框架,譬如Dcloud的HTML5+,釘釘里的DD API,自己也嘗試過不同的方式,
最終發現導航欄的最好做法還是由原生提供,核心原因如下:
- H5頁面載入過程會有白屏問題(也別是弱網路情況),如果整個頁面都是H5實現,那麼白屏了就體驗非常差,而且連基本的交互與操作都沒了
僅基於這一點,就已經拍板了由Native導航欄組件+webview(載入H5)來組成頁面,而原生提供一些API來供網頁操控導航欄(譬如標題,按鈕等)
整體頁面佈局如下:
而H5端可以通過原生提供的API來操控導航欄,以下舉例為quick中規劃的API:
// 僅提供一部分示例
quick.navigator.setTitle({
title: '標題',
subTitle: '子標題',
success: function(result) {},
error: function(error) {}
});
quick.navigator.setRightBtn({
isShow: 1,
text: '按鈕右1',
// 設置圖片的優先順序會較高
//imageUrl: 'http://xxx/test.png',
// 從右數起第幾個
which: 0,
success: function(result) {
/**
* 按鈕點擊後回調
*/
},
error: function(error) {}
});
多tab頁面也由原生提供
實際開發中Native導航欄組件+webview也就滿足絕大部分的頁面需求了,但是還有一些特殊頁面是這種實現達不到的,譬如多Tab頁面
上述這種內含多tab的頁面,每一個tab里都是單獨的頁面,而且可以通過滑動等手勢來切換,甚至tab還會有一些漸變動畫,導航欄也配合改變等(常見於APP首頁)
為了統一實現,這類頁面的導航欄與底部tab均是由原生實現,由H5通過API打開這類原生頁面,並將需要載入的網頁地址傳入,如下
quick.page.openLocal({
className: '那種原生頁面的標識,可以唯一查詢到相應的界面',
data: {
// 需要載入的n個url
url1: 'http://...',
urln: 'http://...',
},
success: function(result) {},
error: function(error) {}
});
然後,在每一個前端頁面(webview裡加載的內容),可以分別在對於頁面的腳本里進行自己的交互控制
重要的業務頁面由原生實現
對於一些重要的業務頁面,如登陸,註冊,支付等,處於安全性以及交互性的考慮(就是一個APP的門面),會採用完全由Native實現
(當然了,一般這些頁面的變動頻率也不大)
一些預設提示頁面採用原生實現
webview載入網頁時,一般情況原生都是會對載入情況進行監聽的,比如是否網路異常。伺服器響應異常,頁面載入崩潰等,
為了防止APP假死,原生會提高一些預設提示頁面
上述只是一個原型示例,實際上,很多情況都可以由原生提供統一提示頁面,
如404,頁面崩潰,網路錯誤等
交互性強、動畫複雜的頁面採用原生實現
除了關鍵性頁面,還有一類,就是H5不好實現的(或者說達不到要求的、實現代價過大的),也應該由原生實現
譬如以某圖像處理軟體某個界面截圖為例
這種頁面涉及到了明顯不太適合H5實現的圖像處理,因此原生才是更佳的選擇(當然了,實際上H5的canvas是由圖像處理能力的)
系統級UI由原生統一實現
前面提到了頁面的選擇,但頁面內的內容也是需要抉擇的,比如一些UI顯示控制項(alert,toast等)
雖然H5完成可以實現這些UI控制項,並且可以和原生模擬的一樣,但是基於以下考慮,所有系統級的UI全部由原生實現並提供API:(原生和H5需統一風格)
每一個合格的原生應用本身就會有一套自己風格的UI,因此不存在重覆開發問題
H5本身可以實現這些組件,但是如果要模擬的和原生一摸一樣的話代價並不小,而且體驗並不能完全接近原生(比如遮罩無法覆蓋導航欄)
如果是原生提供的,更改風格時原生改掉就行了,其它無效變動,如果H5單獨維護一套,那麼就被迫一起同步,平白新增很多的工作量
而且H5還會存在一些坐標、尺寸計算偏差問題
一般情況下H5通過如下API即可調用
quick.ui.toast('xxxx');
quick.ui.alert('xxxx');
quick.ui.alert({
title: "標題",
message: "信息",
buttonName: "確定",
success: function(result) {
// 點擊 alert的按鈕後回調
},
error: function(err) {}
});
頁面切換的轉場由原生實現
一般PC瀏覽器中,頁面之間的調整直接通過a標簽
完成(或者改變href
跳轉),
但是這種跳轉有一個缺點:
無法使用轉場動畫,每次都是乾巴巴的等瀏覽器載入進度條,體驗很差
因此針對這種情況,原生需要提供特點的API來供頁面調用,可以有原生轉場動畫,在新的webview中打開這個頁面
quick.page.open({
pageUrl: "./xxx.html",
data: {
// 額外傳遞的數據
key1: 'value1'
},
success: function(result) {},
error: function(error) {}
});
採用這種方式打開的頁面不再是在本webview中跳轉,而是直接用新的webview打開,有過渡動畫,而且以前的頁面仍然存在記憶體中,接近原生體驗
譬如
頁面A -> 頁面B -> 頁面C
可以看到,如果是直接調整,頁面A和B是不存存在的,而是會被替換,但是採用原生webview打開後,三個頁面同時存在
仍然支持第三方頁面的href跳轉
雖然說可以有API打開的增強方式,但是仍然需要支持href跳轉,這在集成第三方頁面時十分重要(將已經寫好的第三方純網頁集成到容器中,作為某個子模塊)
這裡有一點需要註意:
這類頁面一般由a標簽或href跳轉直接打開,沒有轉場動畫,但是需要webview容器保存訪問歷史記錄,
以避免多次跳轉後一個後退就直接退出了整個模塊
CPU密集型任務、底層的優化要由原生完成
當涉及到一些大量計算時,儘量避免直接在網頁端完成,而是應該由原生提供API完成。
譬如對一張圖片進行圖像處理(曝光、水印、壓縮等等),如果直接由網頁完成的話會發現非常卡,發熱也嚴重,而原生則沒有這麼多的問題
關於底層優化,其實整套混合開發框架中,底層容器的實現是核心部分
容器是否健壯,優化的如何,直接影響整個應用的體驗
關於原生容器應該如何進行優化,後續會有專門的文章,這裡不贅述,只是稍微提及一下:
支持H5頁面的離線訪問(有線上版本和離線版本,通過本地路由表映射)
離線資源動態更新(結合離線訪問一起,比較複雜)
資源緩存(如圖片的緩存,腳本樣式的緩存等)
統一數據埋點採樣等(手機應用使用數據)
ajax請求等等(還有很多,不一一列舉)
能用H5實現的就儘量不要用原生
接下來就是在實際開發過程遵循的準則:
- 能用H5實現的就儘量不要用原生
乍看之下可能和上述的有矛盾,但其實又是合理的,在排除了一些不適合H5實現的頁面,剩餘的絕大部分都是普通的業務頁面,
這類頁面基本可以毫無壓力的採用H5。
所以,這時候,第一想法都是採用H5完成(因為一套代碼可以在至少三個平臺運行-瀏覽器,Android,iOS),
遇到一些比較困難的頁面再去考慮原生實現(從開發效率上,維護代價上,更新方便上都比較麻煩)
那些H5開發中遇到最多的頁面
最後,看下實際開發過程中遇到的最多的頁面吧(以實際遇到的N
個項目的總結)
列表頁面(下拉刷新,載入更多)
純詳情展示頁面(標題,關鍵字,內容)
九宮格首頁
圖片輪播(時常結合列表和九宮格)
標準的表單提交頁面
沒錯,80%
都是上述這種可以算非常簡單的頁面。
譬如封裝過一個下拉刷新組件,基本別人基於這個組件來開發,列表的代碼幾乎是千篇一律。(當然了,剝離了業務邏輯而言)
結束語
時至今日,Hybrid
模式已經過了它最火的時候,市面上也出現如weex
,react-native
等直接寫原生組件的框架,
但是,現在使用最多,應用最廣的仍然要屬這種傳統的Hybrid模式,它已經進入了穩定期(可以說,傳統H5開發(泛概念)不被APP淘汰,這種模式很難被擠下舞臺)
返回根目錄
源碼
github
上這個框架的實現