關於MUI提前注入5+API的嘗試

HBuilder是在開發hybrid app時不錯的工具。爲了使hybrid app的性能更加接近原生,程序猿們做了很多努力。例如近日在HBuilder7.5.0版本中,增加了一個振奮人心的特性。

Android平臺新增提前注入5+ API,支持在plusready事件前調用,具體參考http://ask.dcloud.net.cn/article/921

以往在5+ Runtime環境中,通常情況下需要html頁面解析完成後纔會注入5+ API,執行的順序爲:
1. 加載html頁面
2. 解析html頁面(下載script/link等節點引用的資源,如js/css文件)
3. 觸發DOMContentLoaded事件
4. 注入5+ API
5. 觸發plusready事件

這樣導致5+ API生效時間比較延後,在html中引用js執行之後才能調用5+ AP,於是很多人選擇在plusready時間中編寫邏輯代碼,這樣寫的最大缺點是使腳本的執行時間稍微延後了,如果在頁面的DOMContentLoaded(mui.ready)事件中處理邏輯代碼,會在一定程度上提升頁面加載速度。但是,往往在邏輯代碼中需要調用5+API,怎麼辦呢?
於是在不斷對性能較爲挑剔的程序猿們先在ready事件中處理與5+API無關的頁面邏輯(渲染頁面等);然後在plusready事件中處理需要調用5+API的邏輯代碼。這樣在一定程序上提升了APP的體驗及速度,但卻使代碼分散各處,不利於管理。

此次提前加載5+API突破了這個限制,以下是官方示例:

在HBuilder7.5版本之後將支持提前注入5+ API,可以在plusready事件觸發之前調用5+ API,操作方法是在頁面中添加以下節點:
<script src="html5plus://ready"/>,示例如下:
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8"/>
        <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no"/>
        <title>HTML5+ API</title>
        <script src="html5plus://ready"/>
        <script type="text/javascript" charset="utf-8">
// 這裏可以調用5+ API了,爲了更好的兼容性,應該使用以下代碼進行判斷
if(window.plus){
    // 在這裏調用5+ API
}else{// 兼容老版本的plusready事件
    document.addEventListener('plusready',function () {
        // 在這裏調用5+ API
    },false);
}
        </script>
    </head>
    <body>
Hello HTML5 plus.
    </body>
</html>
注意
1. 僅僅是提前注入5+ API,並不會提前觸發plusready事件(僅步驟4提前操作了)
2. Android3.0及以上平臺才支持提前注入,Android2.*版本無法提前注入
3. 在流應用環境中的wap2app會自動提前注入(第一次引用網絡js時注入),不需要添加<script src="html5plus://ready"/>節點

官方示例中,通過判斷判斷window.plus對象來判斷plus模塊是否已經加載完畢,如果加載完畢則可直接調用,由於plusready事件並沒有提前,所以如同以往使用

document.addEventListener('plusready',function () {
// 在這裏調用5+ API
},false);

來添加監聽,跟以往沒有任何差別。

但是在使用過程中,我發現5+API可能在mui對象加載完畢前已經加載好了,於是在官方示例中的if語句成立時調用mui方法會導致mui未定義的情況。所以我把實例中的:

if(window.plus)

改成:

if(window.plus && window.mui)

但是這樣如果plus加載完畢但mui未加載完畢時可能在效率上並沒有提升。所以我又做了一下修改,在mui.ready中調用window.plus判斷:

mui.ready(function(){
    if(window.plus){
        // 在這裏調用5+ API
    }
});

提前加載H5 plus之後,還會導致滾動條不正常,出現

Object <error> has no method 'endPullupToRefresh'

錯誤,該情況暫無找到解決方案。
與此同時會出現更奇怪的事情,當子Webview提前加載H5 plus而父Webview沒有提前加載時,會導致子Webview的父Webview錯亂,調用.parent()方法查找父Webview時會找到一個奇怪的Webview,對該Webview調用.children()方法找到的子Webview列表中也找不到它。此問題浪費了我三天時間,在這裏隨筆記下,希望不要有人跟我一樣踩進這雷區。

這樣似乎在性能上有一定提升,但我並不確定這樣是否是最好的方法,或者這樣是否會導致其他問題,還望指點。

另外,使用官方示例過程中還有一點不是很確定,就是在if(window.plus)中處理dom元素時可能會出現找不到的情況,此時將<script src="html5plus://ready"></script>註釋掉就不會了。初步猜測可能是因爲plus對象在DOMContentLoaded前就已經加載完畢了,此時頁面並未渲染完造成的。

H5 app的優化之路還很長,繼續埋頭寫代碼去了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章