【quickhybrid】H5和原生的職責劃分

前言

在JSBridge實現後,前端網頁與原生的交互已經通了,接下來就要開始規劃API,明確須要提供哪一些功能來供前端調用。html

可是在這以前,還有一點重要工做須要作:前端

明確H5與Native的職責劃分,肯定哪一些功能能夠由H5實現,哪一些功能只能由原生實現react

Native與H5職責劃分

使用Hybrid模式,用H5開發頁面的本質是:git

減小工做量(一套代碼,多個平臺),以及快速的更新迭代(譬如線上更新),並且還須要考慮Native端的高性能以及系統API調用能力(不然直接用純H5就能夠了)github

所以在進行職責劃分時,就得充分的考慮前端渲染,JS語言以及原生渲染,Java/OC等語言的特性,基本總結以下:web

  • 混合頁面導航欄組件由原生實現ajax

  • 一些重要的業務頁面、帶有複雜動畫或交互的頁面以及一些固定頁面由原生實現canvas

  • 系統級UI由原生統一實現segmentfault

  • 頁面切換的轉場由原生實現react-native

  • 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模式已通過了它最火的時候,市面上也出現如weexreact-native等直接寫原生組件的框架, 可是,如今使用最多,應用最廣的仍然要屬這種傳統的Hybrid模式,它已經進入了穩按期(能夠說,傳統H5開發(泛概念)不被APP淘汰,這種模式很難被擠下舞臺)

返回根目錄

源碼

github上這個框架的實現

quickhybrid/quickhybrid

附錄

參考資料

相關文章
相關標籤/搜索