HTML5 極簡的JS函數


頁面初始化

mui框架將很多功能配置都集中在mui.init方法中,要使用某項功能,只需要在mui.init方法中完成對應參數配置即可,目前支持在mui.init方法中配置的功能包括:創建子頁面、關閉頁面、手勢事件配置、預加載、下拉刷新、上拉加載。

在app開發中,若要使用HTML5+擴展api,必須等plusready事件發生后才能正常使用,mui將該事件封裝成了mui.plusReady()方法,涉及到HTML5+的api,建議都寫在mui.plusReady方法中。如下為打印當前頁面URL的示例:

mui.plusReady(function(){ console.log("當前頁面URL:"+plus.webview.currentWebview().getURL()); });

          

創建子頁面

在mobile app開發過程中,經常遇到卡頭卡尾的頁面,此時若使用局部滾動,在android手機上會出現滾動不流暢的問題; mui的解決思路是:將需要滾動的區域通過單獨的webview實現,完全使用原生滾動。具體做法則是:將目標頁面分解為主頁面和內容頁面,主頁面顯示卡頭卡尾區域,比如頂部導航、底部選項卡等;內容頁面顯示具體需要滾動的內容,然后在主頁面中調用mui.init方法初始化內容頁面。

mui.init({ subpages:[{ url:your-subpage-url,//子頁面HTML地址,支持本地地址和網絡地址 id:your-subpage-id,//子頁面標志 styles:{ top:subpage-top-position,//子頁面頂部位置 bottom:subpage-bottom-position,//子頁面底部位置 width:subpage-width,//子頁面寬度,默認為100% height:subpage-height,//子頁面高度,默認為100% ...... }, extras:{}//額外擴展參數 }] });

參數說明:styles表示窗口屬性,參考5+規范中的WebviewStyle;特別注意,height和width兩個屬性,即使不設置,也默認按100%計算;因此若設置了top值為非"0px"的情況,建議同時設置bottom值,否則5+ runtime根據高度100%計算,可能會造成頁面真實底部位置超出屏幕范圍的情況;left、right同理。

示例:Hello mui的首頁其實就是index.html加list.html合並而成的,如下:

          
index.html
+
         
list.html
=
        
合並后的首頁

index.html的作用就是顯示固定導航,list.html顯示具體列表內容,列表項的滾動是在list.html所在webview中使用原生滾動,既保證了滾動條不會穿透頂部導航,符合app的體驗,也保證了列表流暢滾動,解決了區域滾動卡頓的問題。 list.html就是index.html的子頁面,創建代碼比較簡單,如下:

mui.init({ subpages:[{ url:'list.html', id:'list.html', styles:{ top:'45px',//mui標題欄默認高度為45px; bottom:'0px'//默認為0px,可不定義; } }] });

          

打開新頁面

做web app,一個無法避開的問題就是轉場動畫;web是基於鏈接構建的,從一個頁面點擊鏈接跳轉到另一個頁面,如果通過有刷新的打開方式,用戶要面對一個空白的頁面等待;如果通過無刷新的方式,用Javascript移入DOM節點(常見的SPA解決方案),會碰到很高的性能挑戰:DOM節點繁多,頁面太大,轉場動畫不流暢甚至導致瀏覽器崩潰; mui的解決思路是:單webview只承載單個頁面的dom,減少dom層級及頁面大小;頁面切換使用原生動畫,將最耗性能的部分交給原生實現.

mui.openWindow({
    url:new-page-url,
    id:new-page-id,
    styles:{
      top:newpage-top-position,//新頁面頂部位置
      bottom:newage-bottom-position,//新頁面底部位置
      width:newpage-width,//新頁面寬度,默認為100%
      height:newpage-height,//新頁面高度,默認為100%
      ......
    },
    extras:{
      .....//自定義擴展參數,可以用來處理頁面間傳值
    },
    createNew:false,//是否重復創建同樣id的webview,默認為false:不重復創建,直接顯示
    show:{
      autoShow:true,//頁面loaded事件發生后自動顯示,默認為true
      aniShow:animationType,//頁面顯示動畫,默認為”slide-in-right“;
      duration:animationTime//頁面動畫持續時間,Android平台默認100毫秒,iOS平台默認200毫秒;
    },
    waiting:{
      autoShow:true,//自動顯示等待框,默認為true
      title:'正在加載...',//等待對話框上顯示的提示內容
      options:{
        width:waiting-dialog-widht,//等待框背景區域寬度,默認根據內容自動計算合適寬度
        height:waiting-dialog-height,//等待框背景區域高度,默認根據內容自動計算合適高度
        ......
      }
    }
})

參數說明:

  • styles表示窗口參數,參考5+規范中的WebviewStyle;特別注意,height和width兩個屬性,即使不設置,也默認按100%計算;因此若設置了top值為非"0px"的情況,建議同時設置bottom值,否則5+ runtime根據高度100%計算,可能會造成頁面真實底部位置超出屏幕范圍的情況;left、right同理。  
  • extras:新窗口的額外擴展參數,可用來處理頁面間傳值;例如:var webview = mui.openWindow({url:'info.html',extras:{name:'mui'}});console.log(webview.name);,會輸出"mui"字符串;注意:擴展參數僅在打開新窗口時有效,若目標窗口為預加載頁面,則通過mui.openWindow方法打開時傳遞的extras參數無效。
  • createNew:是否重復創建相同id的webview;為優化性能、避免app中重復創建webview,mui v1.7.0開始增加createNew參數,默認為false;判斷邏輯如下:若createNew為true,則不判斷重復,每次都新建webview;若為fasle,則先計算當前App中是否已存在同樣id的webview,若存在則直接顯示;否則新創建並根據show參數執行顯示邏輯;該參數可能導致的影響:若業務寫在plusReady事件中,而plusReady事件僅首次創建時會觸發,則下次再次通過mui.openWindow方法打開同樣webview時,是不會再次觸發plusReady事件的,此時可通過自定義事件觸發;案例參考:http://ask.dcloud.net.cn/question/6514;  
  •     show表示窗口顯示控制。autoShow:目標窗口loaded事件發生后,是否自動顯示;若目標頁面為預加載頁面,則該參數無效;aniShow表示頁面顯示動畫,比如從右側划入、從下側划入等,具體可參考5+規范中的AnimationTypeShow  
  • waiting表示系統等待框;mui框架在打開新頁面時等待框的處理邏輯為:顯示等待框-->創建目標頁面webview-->目標頁面loaded事件發生-->關閉等待框;因此,只有當新頁面為新創建頁面(webview)時,會顯示等待框,否則若為預加載好的頁面,則直接顯示目標頁面,不會顯示等待框。waiting中的參數:autoShow表示自動顯示等待框,默認為true,若為false,則不顯示等待框;注意:若顯示了等待框,但目標頁面不自動顯示,則需在目標頁面中通過如下代碼關閉等待框plus.nativeUI.closeWaiting();。title表示等待框上的提示文字,options表示等待框顯示參數,比如寬高、背景色、提示文字顏色等,具體可參考5+規范中的WaitingOption

示例1:Hello mui中,點擊首頁右上角的圖標,會打開關於頁面,實現代碼如下:

//tap為mui封裝的單擊事件,可參考手勢事件章節 document.getElementById('info').addEventListener('tap', function() { //打開關於頁面 mui.openWindow({ url: 'examples/info.html', id:'info' }); });

因沒有傳入styles參數,故默認全屏顯示;也沒有傳入show參數,故使用slide-in-right動畫,新頁面從右側滑入。

示例2:從A頁面打開B頁面,B頁面為一個需要從服務端加載的列表頁面,若在B頁面loaded事件發生時就將其顯示出來,因服務器數據尚未加載完畢,列表頁面為空,用戶體驗不好;可通過如下方式改善用戶體驗(最好的用戶體驗應該是通過預加載的方式):第一步,B頁面loaded事件發生后,不自動顯示;

//A頁面中打開B頁面,設置show的autoShow為false,則B頁面在其loaded事件發生后,不會自動顯示; mui.openWindow({ url: 'B.html', show:{ autoShow:false } });

第二步,在B頁面獲取列表數據后,再關閉等待框、顯示B頁面

//B頁面onload從服務器獲取列表數據; window.onload = function(){ //從服務器獲取數據 .... //業務數據獲取完畢,並已插入當前頁面DOM; //注意:若為ajax請求,則需將如下代碼放在處理完ajax響應數據之后; mui.plusReady(function(){ //關閉等待框 plus.nativeUI.closeWaiting(); //顯示當前頁面 mui.currentWebview.show(); }); }

      

關閉頁面

mui框架將窗口關閉功能封裝在mui.back方法中,具體執行邏輯是:

  • 若當前webview為預加載頁面,則hide當前webview;
  • 否則,close當前webview;

在mui框架中,有三種操作會觸發頁面關閉(執行mui.back方法):

  • 點擊包含.mui-action-back類的控件
  • 在頁面上,向右快速滑動
  • Android手機按下back按鍵

hbuilder中敲mheader生成的代碼塊,會自動生成帶有返回導航箭頭的標題欄,點擊返回箭頭可關閉當前頁面,原因就是因為該返回箭頭包含.mui-action-back類,代碼如下:

<header class="mui-bar mui-bar-nav"> <a class="mui-action-back mui-icon mui-icon-left-nav mui-pull-left"></a> <h1 class="mui-title">標題</h1> </header>

若希望在頂部導航欄之外的其它區域添加關閉頁面的控件,只需要在對應控件上添加.mui-action-back類即可,如下為一個關閉按鈕示例:

<button type="button" class='mui-btn mui-btn-danger mui-action-back'>關閉</button>

mui框架封裝的頁面右滑關閉功能,默認未啟用,若要使用右滑關閉功能,需要在mui.init();方法中設置swipeBack參數,如下:

mui.init({ swipeBack:true //啟用右滑關閉功能 });

mui框架默認會監聽Android手機的back按鍵,然后執行頁面關閉邏輯; 若不希望mui自動處理back按鍵,可通過如下方式關閉mui的back按鍵監聽;

mui.init({ keyEventBind: { backbutton: false //關閉back按鍵監聽 } });

除了如上三種操作外,也可以直接調用mui.back()方法,執行窗口關閉邏輯;

mui.back()僅處理窗口邏輯,若希望在窗口關閉之前再處理一些其它業務邏輯,則可將業務邏輯抽象成一個具體函數,然后注冊為mui.init方法的beforeback參數;beforeback的執行邏輯為:

  • 執行beforeback參數對應的函數若返回false,則不再執行mui.back()方法;
  • 否則(返回true或無返回值),繼續執行mui.back()方法;

示例:從列表打開詳情頁面,從詳情頁面再返回后希望刷新列表界面,此時可注冊beforeback參數,然后通過自定義事件通知列表頁面刷新數據,示例代碼如下:

mui.init({ beforeback: function(){ //獲得列表界面的webview var list = plus.webview.getWebviewById('list'); //觸發列表界面的自定義事件(refresh),從而進行數據刷新 mui.fire(list,'refresh'); //返回true,繼續頁面關閉邏輯 return true; } });

注意:beforeback的執行返回必須是同步的(阻塞模式),若使用nativeUI這種異步js(非阻塞模式),則可能會出現意想不到的結果;比如:通過plus.nativeUI.confirm()彈出確認框,可能用戶尚未選擇,頁面已經返回了(beforeback同步執行完畢,無返回值,繼續執行mui.back()方法,nativeUI不會阻塞js進程):在這種情況下,若要自定義業務邏輯,就需要復寫mui.back方法了;如下為一個自定義示例,每次都需要用戶確認后,才會關閉當前頁面

//備份mui.back,mui.back已將窗口關閉邏輯封裝的比較完善(預加載及父子窗口),因此最好復用mui.back var old_back = mui.back; mui.back = function(){ var btn = ["確定","取消"]; mui.confirm('確認關閉當前窗口?','Hello MUI',btn,function(e){ if(e.index==0){ //執行mui封裝好的窗口關閉邏輯; old_back(); } }); }

注意:自定義關閉邏輯時,一定要重寫mui.back,不能簡單通過addEventListener增加back按鍵監聽, 因為addEventListener只會增加新的執行邏輯,老的監聽邏輯依然會執行;

      

Ajax

mui框架基於htm5plus的XMLHttpRequest,封裝了常用的Ajax函數,支持GET、POST請求方式,支持返回json、xml、html、text、script數據類型; 本着極簡的設計原則,mui提供了mui.ajax方法,並在mui.ajax方法基礎上,進一步簡化出最常用的mui.get()、mui.getJSON()、mui.post()三個方法。

mui.ajax()方法通過HTTP請求加載遠程數據,是mui框架底層Ajax的實現方法,使用方法:mui.ajax(url[,setting]),其中url表示請求發送的目標地址,setting是一個json對象,支持的參數主要包括:

參數 類型 描述
data Object 發送到服務器的數據,可以是json對象或字符串
dataType String 預期服務器返回的數據類型;如果不指定,mui將自動根據HTTP包的MIME頭信息自動判斷;支持設置的dataType可選值:
  • "xml": 返回XML文檔
  • "html": 返回純文本HTML信息;
  • "script": 返回純文本JavaScript代碼
  • "json": 返回JSON數據
  • "text": 返回純文本字符串
error Function 請求失敗時觸發的函數,該函數接收三個參數:
  • xhr:xhr實例對象,類型是XMLHttpRequest
  • type:錯誤描述,類型是String,可取值除了'null'外,其它可能值:"timeout", "error", "abort", "parsererror"
  • errorThrown:可捕獲的異常對象,類型是String
success Function 請求成功時觸發的回調函數,該函數接收三個參數:
  • data:服務器返回的響應數據,類型可以是json對象、xml對象、字符串等;
  • textStatus:狀態描述,參數類型是String,默認值為'success'
  • xhr:xhr實例對象,類型是XMLHttpRequest
timeout Number 請求超時時間(毫秒),默認值為0,表示永不超時;若超過設置的超時時間(非0的情況),依然未收到服務器響應,則觸發error回調
type String 請求方式,目前僅支持'GET'和'POST',默認為'GET'方式

代碼示例:如下為通過post方式向某服務器發送鑒權登錄的代碼片段

mui.ajax('http://server-name/login.php',{ data:{ username:'username', password:'password' }, dataType:'json',//服務器返回json格式數據 type:'post',//HTTP請求類型 timeout:10000,//超時時間設置為10秒; success:function(data){ //服務器返回響應,根據響應結果,分析是否登錄成功; ... }, error:function(xhr,type,errorThrown){ //異常處理; console.log(type); } });

mui.post()方法是對mui.ajax()的一個簡化方法,直接使用POST請求方式向服務器發送數據、且不處理timeout和異常(若需處理異常及超時,請使用mui.ajax()方法),使用方法: mui.post(url[,data][,success][,dataType]),如上登錄鑒權代碼換成mui.post()后,代碼更為簡潔,如下:

mui.post('http://server-name/login.php',{ username:'username', password:'password' },function(data){ //服務器返回響應,根據響應結果,分析是否登錄成功; ... },'json' );

mui.get()方法和mui.post()方法類似,只不過是直接使用GET請求方式向服務器發送數據、且不處理timeout和異常(若需處理異常及超時,請使用mui.ajax()方法),使用方法: mui.get(url[,data][,success][,dataType]),如下為獲得某服務器新聞列表的代碼片段,服務器以json格式返回數據列表

mui.get('http://server-name/list.php',{category:'news'},function(data){ //獲得服務器響應 ... },'json' );

如上mui.get()方法和如下mui.ajax()方法效果是一致的:

 

mui.ajax('http://server-name/list.php',{ data:{ category:'news' }, dataType:'json',//服務器返回json格式數據 type:'get',//HTTP請求類型 success:function(data){ //獲得服務器響應 ... } });

mui.getJSON()方法是在mui.get()方法基礎上的更進一步簡化,限定返回json格式的數據,其它參數和mui.get()方法一致,使用方法: mui.get(url[,data][,success]),如上獲得新聞列表的代碼換成mui.getJSON()方法后,更為簡潔,如下:

mui.getJSON('http://server-name/list.php',{category:'news'},function(data){ //獲得服務器響應 ... } );

          

手勢事件

在開發移動端的應用時,會用到很多的手勢操作,比如滑動、長按等,為了方便開放者快速集成這些手勢,mui內置了常用的手勢事件,目前支持的手勢事件見如下列表:

分類 參數 描述
點擊 tap 單擊屏幕
doubletap 雙擊屏幕
長按 longtap 長按屏幕
hold 按住屏幕
release 離開屏幕
滑動 swipeleft 向左滑動
swiperight 向右滑動
swipeup 向上滑動
swipedown 向下滑動
拖動 dragstart 開始拖動
drag 拖動中
dragend 拖動結束

      

手勢事件配置

根據使用頻率,mui默認會監聽部分手勢事件,如點擊、滑動事件;為了開發出更高性能的moble App,mui支持用戶根據實際業務需求,通過mui.init方法中的gestureConfig參數,配置具體需要監聽的手勢事件,。

mui.init({ gestureConfig:{ tap: true, //默認為true doubletap: true, //默認為false longtap: true, //默認為false swipe: true, //默認為true drag: true, //默認為true hold:false,//默認為false,不監聽 release:false//默認為false,不監聽 } });

注意:dragstart、drag、dragend共用drag開關,swipeleft、swiperight、swipeup、swipedown共用swipe開關

事件監聽

同標准click事件一樣,上述手勢事件支持添加到任意DOM對象上,如下為一個示例:

elem.addEventListener("swipeleft",function(){ console.log("你正在向左滑動"); });

        

預加載

所謂的預加載技術就是在用戶尚未觸發頁面跳轉時,提前創建目標頁面,這樣當用戶跳轉時,就可以立即進行頁面切換,節省創建新頁面的時間,提升app使用體驗。mui提供兩種方式實現頁面預加載。

方式一:通過mui.init方法中的preloadPages參數進行配置.

mui.init({ preloadPages:[ { url:prelaod-page-url, id:preload-page-id, styles:{},//窗口參數 extras:{},//自定義擴展參數 subpages:[{},{}]//預加載頁面的子頁面 } ] });

該種方案使用簡單、可預加載多個頁面,但不會返回預加載每個頁面的引用,若要獲得對應webview引用,還需要通過plus.webview.getWebviewById方式獲得;另外,因為mui.init是異步執行,執行完mui.init方法后立即獲得對應webview引用,可能會失敗,例如如下代碼:    

mui.init({ preloadPages:[ { url:'list.html', id:'list' } ] }); var list = plus.webview.getWebviewByid('list');//這里可能返回空;

方式二:通過mui.preload方法預加載.

var page = mui.preload({ url:new-page-url, id:new-page-id,//默認使用當前頁面的url作為id styles:{},//窗口參數 extras:{}//自定義擴展參數 });

通過mui.preload()方法預加載,可立即返回對應webview的引用,但一次僅能預加載一個頁面;若需加載多個webview,則需多次調用mui.preload()方法;

如上兩種方案,各有優劣,需根據具體業務場景靈活選擇;

        

下拉刷新

        為實現下拉刷新功能,大多H5框架都是通過DIV模擬下拉回彈動畫,在低端android手機上,DIV動畫經常出現卡頓現象(特別是圖文列表的情況);         mui通過雙webview解決這個DIV的拖動流暢度問題;拖動時,拖動的不是div,而是一個完整的webview(子webview),回彈動畫使用原生動畫;在iOS平台,H5的動畫已經比較流暢,故依然使用H5方案。兩個平台實現雖有差異,但mui經過封裝,可使用一套代碼實現下拉刷新。

主頁面內容比較簡單,只需要創建子頁面即可:

mui.init({ subpages:[{ url:pullrefresh-subpage-url,//下拉刷新內容頁面地址 id:pullrefresh-subpage-id,//內容頁面標志 styles:{ top:subpage-top-position,//內容頁面頂部位置,需根據實際頁面布局計算,若使用標准mui導航,頂部默認為48px; .....//其它參數定義 } }] });

內容頁面需按照如下DOM結構構建:

<!--下拉刷新容器--> <div id="refreshContainer" class="mui-content mui-scroll-wrapper"> <div class="mui-scroll"> <!--數據列表--> <ul class="mui-table-view mui-table-view-chevron"> </ul> </div> </div>

其次,通過mui.init方法中pullRefresh參數配置下拉刷新各項參數,如下:

mui.init({ pullRefresh : { container:"#refreshContainer",//下拉刷新容器標識,querySelector能定位的css選擇器均可,比如:id、.class等 down : { contentdown : "下拉可以刷新",//可選,在下拉可刷新狀態時,下拉刷新控件上顯示的標題內容 contentover : "釋放立即刷新",//可選,在釋放可刷新狀態時,下拉刷新控件上顯示的標題內容 contentrefresh : "正在刷新...",//可選,正在刷新狀態時,下拉刷新控件上顯示的標題內容 callback :pullfresh-function //必選,刷新函數,根據具體業務來編寫,比如通過ajax從服務器獲取新數據; } } });

最后,根據具體業務編寫刷新函數,需要注意的是,加載完新數據后,需要執行endPulldownToRefresh()方法;

function pullfresh-function() { //業務邏輯代碼,比如通過ajax從服務器獲取新數據; ...... //注意,加載完新數據后,必須執行如下代碼,注意:若為ajax請求,則需將如下代碼放置在處理完ajax響應數據之后 mui('#refreshContainer').pullRefresh().endPulldownToRefresh(); }

        

上拉加載

mui的上拉加載實現比較簡單,檢測5+ runtime提供的滾動條滾動到底事件(plusscrollbottom),顯示“正在加載”提示-->開始加載業務數據-->隱藏"正在加載"提示。使用方式類似下拉刷新,首先、通過mui.init方法中pullRefresh參數配置上拉加載各項參數,如下:

mui.init({ pullRefresh : { container:refreshContainer,//待刷新區域標識,querySelector能定位的css選擇器均可,比如:id、.class等 up : { contentrefresh : "正在加載...",//可選,正在加載狀態時,上拉加載控件上顯示的標題內容 contentnomore:'沒有更多數據了',//可選,請求完畢若沒有更多數據時顯示的提醒內容; callback :pullfresh-function //必選,刷新函數,根據具體業務來編寫,比如通過ajax從服務器獲取新數據; } } });

其次,根據具體業務編寫加載函數,需要注意的是,加載完新數據后,需要執行endPullupToRefresh()方法;

function pullfresh-function() { //業務邏輯代碼,比如通過ajax從服務器獲取新數據; ...... //注意,加載完新數據后,必須執行如下代碼,true表示沒有更多數據了,兩個注意事項: //1、若為ajax請求,則需將如下代碼放置在處理完ajax響應數據之后 //2、注意this的作用域,若存在匿名函數,需將this復制后使用,參考hello mui中的代碼示例; this.endPullupToRefresh(true|false); }

注意:  

  • 因為使用的是滾動到底事件,因此若當前頁面內容過少,沒有滾動條的話,就不會觸發上拉加載
  • 多次上拉加載后,若已沒有更多數據可加載時,調用this.endPullupToRefresh(true);,之后滾動條滾動到底時,將不再顯示“上拉顯示更多”的提示語,而顯示“沒有更多數據了”的提示語;
  • 若實際業務中,有重新觸發上拉加載的需求(比如當前類別已無更多數據,但切換到另外一個類別后,應支持繼續上拉加載),此時調用上拉加載的重置函數即可,如下代碼:

 

//pullup-container為在mui.init方法中配置的pullRefresh節點中的container參數; mui('#pullup-container').pullRefresh().refresh(true);

        

輸入增強

mui目前提供的輸入增強包括:快速刪除和語音輸入兩項功能。要刪除輸入框中的內容,使用輸入法鍵盤上的刪除按鍵,只能逐個刪除字符,mui提供了快速刪除能力,只需要在對應input控件上添加.mui-input-clear類,當input控件中有內容時,右側會有一個刪除圖標,點擊會清空當前input的內容;另外,為了方便快速輸入,mui集成了HTML5+的語音輸入,只需要在對應input控件上添加.mui-input-speech類,就會在該控件右側顯示一個語音輸入的圖標,點擊會啟用科大訊飛語音輸入界面。

        

開關事件

mui提供了開關控件樣式,點擊滑動兩種手勢都可以對開關控件進行操作,在開關控件進行切換時,會觸發toggle事件,通過事件的detail.isActive屬性可以判斷當前開關狀態。可通過監聽toggle事件,在開關切換時執行特定業務邏輯。如下為使用示例:

document.getElementById("mySwitch").addEventListener("toggle",function(event){ if(event.detail.isActive){ console.log("你啟動了開關"); }else{ console.log("你關閉了開關"); } })

若要獲得當前開關狀態,可通過判斷當前開關控件是否包含.mui-active類來實現,若包含,則為打開狀態,否則即為關閉狀態;如下為代碼示例:

var isActive = document.getElementById("mySwitch").classList.contains("mui-active"); if(isActive){ console.log("打開狀態"); }else{ console.log("關閉狀態"); }

若使用js打開、關閉開關控件,可使用switch插件的toggle()方法,如下為示例代碼:

mui("#mySwitch").switch().toggle();

          

slide事件

mui提供了圖片輪播、可拖動式圖文表格、可拖動式選項卡、左右滑動9宮格組件,這些組件都用到了mui框架的slide插件,有較多共同點。首先,Dom內容構造基本相同,都必須有一個.mui-slider的父容器;其次,當拖動切換顯示內容時,均會觸發slide事件(可拖動式選項卡在點擊選項卡標題時,也會觸發slide事件),通過該事件的detail.slideNumber參數可以獲得當前顯示項的索引(第一項索引為0,第二項為1,以此類推),利用該事件,可在顯示內容切換時,動態處理一些業務邏輯。

如下為一個可拖動式選項卡示例,為提高頁面加載速度,頁面加載時,僅顯示第一個選項卡的內容,第二、第三選項卡內容為空。

<div class="mui-slider"> <!--選項卡標題區--> <div class="mui-slider-indicator mui-segmented-control mui-segmented-control-inverted"> <a class="mui-control-item" href="#item1">待辦公文</a> <a class="mui-control-item" href="#item2">已辦公文</a> <a class="mui-control-item" href="#item3">全部公文</a> </div> <div class="mui-slider-progress-bar mui-col-xs-4"></div> <div class="mui-slider-group"> <!--第一個選項卡內容區--> <div id="item1" class="mui-slider-item mui-control-content mui-active"> <ul class="mui-table-view"> <li class="mui-table-view-cell">待辦公文1</li> <li class="mui-table-view-cell">待辦公文2</li> <li class="mui-table-view-cell">待辦公文3</li> </ul> </div> <!--第二個選項卡內容區,頁面加載時為空--> <div id="item2" class="mui-slider-item mui-control-content"></div> <!--第三個選項卡內容區,頁面加載時為空--> <div id="item3" class="mui-slider-item mui-control-content"></div> </div> </div>

當切換到第二、第三個選項卡時,再動態獲取相應內容進行顯示:

var item2Show = false,item3Show = false;//子選項卡是否顯示標志 document.querySelector('.mui-slider').addEventListener('slide', function(event) { if (event.detail.slideNumber === 1&&!item2Show) { //切換到第二個選項卡 //根據具體業務,動態獲得第二個選項卡內容; var content = .... //顯示內容 document.getElementById("item2").innerHTML = content; //改變標志位,下次直接顯示 item2Show = true; } else if (event.detail.slideNumber === 2&&!item3Show) { //切換到第三個選項卡 //根據具體業務,動態獲得第三個選項卡內容; var content = .... //顯示內容 document.getElementById("item3").innerHTML = content; //改變標志位,下次直接顯示 item3Show = true; } });

圖片輪播、可拖動式圖文表格等均可按照同樣方式監聽內容變化,比如我們可以在圖片輪播界面顯示當前正在看的是第幾張圖片:

document.querySelector('.mui-slider').addEventListener('slide', function(event) { //注意slideNumber是從0開始的; document.getElementById("info").innerText = "你正在看第"+(event.detail.slideNumber+1)+"張圖片"; });

          

自定義事件

用戶開發應用中會大量使用事件功能。除了瀏覽器內置的事件及mui框架內置的事件(比如手勢事件)外,mui同時支持用戶觸發和綁定自定義事件。通過自定義事件,用戶可以輕松實現頁面間數據傳遞。

監聽自定義事件

添加自定義事件監聽操作和標准js事件監聽類似,可直接通過window對象添加,如下:

window.addEventListener('customEvent',function(event){ //通過event.detail可獲得傳遞過來的參數內容 .... });

觸發自定義事件

通過mui.fire方法可觸發目標窗口的自定義事件:

mui.fire(targetPage,'customEvent',{ //自定義事件參數 });

示例:假設如下場景:從新聞列表頁面進入新聞詳情頁面,新聞詳情頁面為共用頁面,通過傳遞新聞ID通知詳情頁面需要顯示具體哪個新聞,詳情頁面再動態向服務器請求數據,mui要實現類似需求可通過如下步驟實現:

  •     在列表頁面中預加載詳情頁面(假設為detail.html)  
  •     列表頁面在點擊新聞標題時,首先,獲得該新聞id,觸發詳情頁面的newsId事件,並將新聞id作為事件參數傳遞過去;然后再打開詳情頁面;  
  • 詳情頁面監聽newsId自定義事件

 

列表頁面代碼如下:

//初始化預加載詳情頁面 mui.init({ preloadPages:[{ id:'detail.html', url:'detail.html' } ] }); var detailPage = null; //添加列表項的點擊事件 mui('.mui-content').on('tap', 'a', function(e) { var id = this.getAttribute('id'); //獲得詳情頁面 if(!detailPage){ detailPage = plus.webview.getWebviewById('detail.html'); } //觸發詳情頁面的newsId事件 mui.fire(detailPage,'newsId',{ id:id }); //打開詳情頁面 mui.openWindow({ id:'detail.html' }); });

詳情頁面代碼如下:

//添加newId自定義事件監聽 window.addEventListener('newsId',function(event){ //獲得事件參數 var id = event.detail.id; //根據id向服務器請求新聞詳情 ..... });

      

圖片輪播

mui框架內置了圖片輪播插件,通過該插件封裝的JS API,用戶可以設定是否自動輪播及輪播周期,如下為代碼示例:

//獲得slider插件對象 var gallery = mui('.mui-slider'); gallery.slider({ interval:5000//自動輪播周期,若為0則不自動播放,默認為0; });

因此若希望圖片輪播不要自動播放,而是用戶手動滑動才切換,只需要通過如上方法,將slideshowDelay參數設為0即可。

若要跳轉到第x張圖片,則可以使用圖片輪播插件的gotoItem方法,例如:

//獲得slider插件對象 var gallery = mui('.mui-slider'); gallery.slider().gotoItem(index);//跳轉到第index張圖片,index從0開始;

圖片輪播涉及的另外一個問題:是否支持循環播放,比如有1、2、3、4四張圖片,從第1張圖片起,依次向左滑動切換圖片,當切換到第4張圖片時,繼續向左滑動,接下來會有兩種效果:  

  • 支持循環:左滑,直接切換到第1張圖片;
  • 不支持循環:左滑,無反應,繼續顯示第4張圖片,用戶若要顯示第1張圖片,必須連續向右滑動切換到第1張圖片;

  當顯示第1張圖片時,繼續右滑是否顯示第4張圖片,是同樣問題;這個問題的實現需要通過.mui-slider-loop類及DOM節點來控制;若不支持循環,代碼比較簡單,如下:

 

<div class="mui-slider"> <div class="mui-slider-group"> <div class="mui-slider-item"><a href="#"><img src="1.jpg" /></a></div> <div class="mui-slider-item"><a href="#"><img src="2.jpg" /></a></div> <div class="mui-slider-item"><a href="#"><img src="3.jpg" /></a></div> <div class="mui-slider-item"><a href="#"><img src="4.jpg" /></a></div> </div> </div>

若要支持循環,則需要在.mui-slider-group節點上增加.mui-slider-loop類,同時需要重復增加2張圖片,圖片順序變為:4、1、2、3、4、1,代碼示例如下:

<div class="mui-slider"> <div class="mui-slider-group mui-slider-loop"> <!--支持循環,需要重復圖片節點--> <div class="mui-slider-item mui-slider-item-duplicate"><a href="#"><img src="4.jpg" /></a></div> <div class="mui-slider-item"><a href="#"><img src="1.jpg" /></a></div> <div class="mui-slider-item"><a href="#"><img src="2.jpg" /></a></div> <div class="mui-slider-item"><a href="#"><img src="3.jpg" /></a></div> <div class="mui-slider-item"><a href="#"><img src="4.jpg" /></a></div> <!--支持循環,需要重復圖片節點--> <div class="mui-slider-item mui-slider-item-duplicate"><a href="#"><img src="1.jpg" /></a></div> </div> </div>

注意:mui框架會默認初始化當前頁面的圖片輪播組件;若輪播組件內容為js動態生成時(比如通過ajax動態獲取的營銷信息),則需要在動態DOM生成后,手動調用圖片輪播的初始化方法;代碼如下:  

//獲得slider插件對象 var gallery = mui('.mui-slider'); gallery.slider({ interval:5000//自動輪播周期,若為0則不自動播放,默認為0; });

      

側滑導航

mui提供了兩種側滑導航實現:webview模式和div模式,兩種模式各有優劣,適用於不同的場景。

webview模式

主頁面和菜單內容在不同的webview中,兩個頁面根據內容需求分別組織DOM結構,mui對其DOM結構無特殊要求,故其有如下優點:

  • 菜單內容是單獨的webview,故可被多個頁面復用;
  • 菜單內容在單獨的webview中,菜單區域的滾動不影響主界面,故可使用原生滾動,滾動更為流暢;

另一方面,webview模式也有其缺點:

  • 不支持拖動手勢(跟手拖動);
  • 主頁面、菜單不同webview實現,因此若需交互(如:點擊菜單觸發主頁面內容變化),需使用自定義事件實現跨webview通訊;

div模式

    主頁面和菜單內容在同一個webview下,嵌套在特定結構的div中,通過div的移動動畫模擬菜單移動;故該模式有如下優點:   

  • 支持拖動手勢(跟手拖動);
  • 主頁面、菜單在一個頁面中,可通過JS輕松實現兩者交互(如:點擊菜單觸發主頁面內容變化),沒有跨webview通訊的煩惱;

另一方面,div模式也有其缺點:

  • 不支持菜單內容在多頁面的復用,需每個頁面都生成對應的菜單節點;
  • 主界面和菜單內容的滾動互不影響,因此會使用div區域滾動,在低端Android手機且滾動內容較多時,可能會稍顯卡頓;

div模式支持不同的動畫效果,每種動畫效果需遵從不同的DOM構造;下面我們以右滑菜單為例(左滑菜單僅需將菜單父節點上的mui-off-canvas-left換成mui-off-canvas-right即可),說明每種動畫對應的DOM結構。

動畫1:主界面移動、菜單不動

<!-- 側滑導航根容器 --> <div class="mui-off-canvas-wrap mui-draggable"> <!-- 菜單容器 --> <aside class="mui-off-canvas-left"> <div class="mui-scroll-wrapper"> <div class="mui-scroll"> <!-- 菜單具體展示內容 --> ... <div> </div> </aside> <!-- 主頁面容器 --> <div class="mui-inner-wrap"> <!-- 主頁面標題 --> <header class="mui-bar mui-bar-nav"> <a class="mui-icon mui-action-menu mui-icon-bars mui-pull-left"></a> <h1 class="mui-title">標題</h1> </header> <div class="mui-content mui-scroll-wrapper"> <div class="mui-scroll"> <!-- 主界面具體展示內容 --> ... </div> </div> </div> </div>

動畫2:主界面不動、菜單移動  

該種動畫要求的DOM結構和動畫1的DOM結構基本相同,唯一差別就是需在側滑導航根容器class上增加一個mui-slide-in

動畫3:主界面、菜單同時移動  

該種動畫要求的DOM結構較特殊,需將菜單容器放在主頁面容器之下

<!-- 側滑導航根容器 --> <div class="mui-off-canvas-wrap mui-draggable"> <!-- 主頁面容器 --> <div class="mui-inner-wrap"> <!-- 菜單容器 --> <aside class="mui-off-canvas-left"> <div class="mui-scroll-wrapper"> <div class="mui-scroll"> <!-- 菜單具體展示內容 --> ... <div> </div> </aside> <!-- 主頁面標題 --> <header class="mui-bar mui-bar-nav"> <a class="mui-icon mui-action-menu mui-icon-bars mui-pull-left"></a> <h1 class="mui-title">標題</h1> </header> <!-- 主頁面內容容器 --> <div class="mui-content mui-scroll-wrapper"> <div class="mui-scroll"> <!-- 主界面具體展示內容 --> ... </div> </div> </div> </div>

mui支持多種方式顯示div模式的側滑菜單:1、在主界面向右拖動(drag);2、點擊含有mui-action-menu類的控件;3、Android手機按menu鍵;4、通過JS API觸發,如下:

mui('.mui-off-canvas-wrap').offCanvas('show');

同樣,mui支持多種方式關閉div模式的側滑菜單:1、在手機屏幕上任意位置向左拖動(drag);2、點擊主界面內任意位置;3、Android手機按menu鍵;4、Android手機按back鍵;5、通過JS API觸發,如下:

mui('.mui-off-canvas-wrap').offCanvas('close');

      

彈出菜單

mui框架內置了彈出菜單插件,彈出菜單顯示內容不限,但必須包裹在一個含.mui-popover類的div中,如下即為一個彈出菜單內容:

<div id="popover" class="mui-popover"> <ul class="mui-table-view"> <li class="mui-table-view-cell"><a href="#">Item1</a></li> <li class="mui-table-view-cell"><a href="#">Item2</a></li> <li class="mui-table-view-cell"><a href="#">Item3</a></li> <li class="mui-table-view-cell"><a href="#">Item4</a></li> <li class="mui-table-view-cell"><a href="#">Item5</a></li> </ul> </div>

要顯示、隱藏如上菜單,mui推薦使用錨點方式,例如:

<a href="#popover" class="mui-btn mui-btn-primary mui-btn-block">打開彈出菜單</a>

點擊如上定義的按鈕,即可顯示彈出菜單,再次點擊彈出菜單之外的其他區域,均可關閉彈出菜單;這種使用方式最為簡潔。

若希望通過js的方式控制彈出菜單,則通過如下一個方法即可:

//傳入toggle參數,用戶也無需關心當前是顯示還是隱藏狀態,mui會自動識別處理; mui('.mui-popover').popover('toggle');

        

遮罩蒙版

在popover、側滑菜單等界面,經常會用到蒙版遮罩;比如popover彈出后,除popover控件外的其它區域都會遮罩一層蒙版,用戶點擊蒙版不會觸發蒙版下方的邏輯,而會關閉popover同時關閉蒙版;再比如側滑菜單界面,菜單划出后,除側滑菜單之外的其它區域都會遮罩一層蒙版,用戶點擊蒙版會關閉側滑菜單同時關閉蒙版。      

遮罩蒙版常用的操作包括:創建、顯示、關閉,如下代碼:

var mask = mui.createMask(callback);//callback為用戶點擊蒙版時自動執行的回調; mask.show();//顯示遮罩 mask.close();//關閉遮罩

注意:關閉遮罩僅會關閉,不會銷毀;關閉之后可以再次調用mask.show();打開遮罩;

mui默認的蒙版遮罩使用.mui-backdrop類定義(如下代碼),若需自定義遮罩效果,只需覆蓋定義.mui-backdrop即可;

.mui-backdrop { position: fixed; top: 0; right: 0; bottom: 0; left: 0; z-index: 998; background-color: rgba(0,0,0,.3); }


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM