今天也是我接觸mui的第一天。首先先上MUI的官網上面瞧一瞧。http://dev.dcloud.net.cn/mui/window/#closewindow我這里上的不是官網,
我是先把他的基本能實現的功能先做了一個簡單的了解。下面大家跟着我看:
一、Mui的組件
mui的組件都很原生比如拓展閱讀,操作表,折疊面板,你需要那個組件就把那個組件拷貝下來,例如你需要折疊面板
<ul class="mui-table-view"> <li class="mui-table-view-cell mui-collapse"> <a class="mui-navigate-right" href="#">面板1</a> <div class="mui-collapse-content"> <p>面板1子內容</p> </div> </li> </ul>
還有單選框,輪播圖,數字角標,消息框,卡片視圖,透明狀態欄,右滑,左滑,等等組件,再將你想要使用的模板復制下來,粘貼到你想要想放進去的地方即可。
二、MUI的窗口
MUI的窗口包括頁面的初始化,創建子頁面,打開新頁面,打開帶原聲帶導航欄的新頁面,關閉頁面,預加載等。
不管你是打一個新頁面還是創建一個新頁面它里面都會夾雜着你想要的動畫效果,比如下拉刷新,下拉刷新打開一個新頁面。
下面拿着頁面初始化來舉一個例子:
在app開發中,若要使用HTML5+擴展api,必須等plusready事件發生后才能正常使用,mui將該事件封裝成了mui.plusReady()
方法,涉及到HTML5+的api,建議都寫在mui.plusReady方法中。如下為打印當前頁面URL的示例:
mui.plusReady(function(){ console.log("當前頁面URL:"+plus.webview.currentWebview().getURL()); });
擴展閱讀
mui.init()
mui插件初始化
mui.ready()
當DOM准備就緒時,指定一個函數來執行。
創建子頁面
在mobile app開發過程中,經常會出現共用的導航欄或者選項卡,每次打開頁面都需要重新渲染,而且容易出現卡頭卡尾的現象。並且此時若使用局部滾動,在android手機上會出現滾動不流暢的問題;
mui現在提供兩種解決方案:
第一種(官方推薦):在plus環境下,使用原生titleNView以及原生tabbar來替換頁面的導航欄或者選項卡。在頁面打開時,渲染已經完成,讓你的應用更接近原生app。具體做法:原生titleNView參考mui.openWindow
的示例3,原生tabbar示例參考ask教程示例
第二種:通過雙webview模式解決,此種情況適用於需要上下拉刷新的列表頁面。將需要滾動的區域通過單獨的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同理。
打開新頁面
做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
新窗口的額外擴展參數,可用來處理頁面間傳值;例如:
注意:擴展參數僅在打開新窗口時有效,若目標窗口為預加載頁面,則通過mui.openWindow方法打開時傳遞的extras參數無效。var webview = mui.openWindow({ url:'info.html', extras:{ name:'mui' //擴展參數 } }); console.log(webview.name);//輸出mui字
-
createNew
是否重復創建相同id的webview;
為優化性能、避免app中重復創建webview,mui v1.7.0開始增加createNew參數,默認為false;判斷邏輯如下:
-
createNew參數為為true,則不判斷重復,每次都新建webview;
-
createNew參數為為fasle,則先查找當前App中是否已存在同樣id的webview,若存在則直接顯示;否則新創建並根據show參數執行顯示邏輯;
注意:plusReady事件僅在webview首次創建時觸發,使用
mui.openWindow
方法多次打開已存在的同樣id的webview時,是不會重復觸發plusReady事件的; 因此若業務寫在plusReady事件中,可能會出現執行結果和預期不一致的情況;此時可通過自定義事件觸發; 案例參考:mui.plusReady有時會失效; -
-
show
窗口顯示控制參數,具體參數如下:
-
autoShow:目標窗口loaded事件發生后,是否自動顯示,默認為true;若為false,則僅創建但不顯示webview;若目標頁面為預加載頁面,則該參數無效;
-
aniShow表示頁面顯示動畫,比如從右側划入、從下側划入等,具體可參考5+規范中的AnimationTypeShow
-
duration:顯示Webview窗口動畫的持續時間,單位為ms
-
-
waiting
系統等待框參數
mui框架在打開新頁面時等待框的處理邏輯為:
顯示等待框-->創建目標頁面webview-->目標頁面loaded事件發生-->關閉等待框;
因此,只有當新頁面為新創建頁面(webview)時,會顯示等待框,否則若為預加載好的頁面,則直接顯示目標頁面,不會顯示等待框。waiting中的具體參數:
-
autoShow:是否自動顯示等待框,默認為true;若為false,則不顯示等待框;注意:若waiting框的autoShow為true,但目標頁面不自動顯示,則需在目標頁面中通過如下代碼關閉等待框:
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的事件包括事件綁定,事件取消,事件觸發,手勢事件。自定義事件。
事件綁定
除了可以使用addEventListener()
方法監聽某個特定元素上的事件外, 也可以使用.on()
方法實現批量元素的事件綁定。
.on( event , selector , handler )
示例
點擊新聞列表,獲取當前列表項的id,並將該id傳給新聞詳情頁面,然后打開新聞詳情頁面
mui(".mui-table-view").on('tap','.mui-table-view-cell',function(){ //獲取id var id = this.getAttribute("id"); //傳值給詳情頁面,通知加載新數據 mui.fire(detail,'getDetail',{id:id}); //打開新聞詳情 mui.openWindow({ id:'detail', url:'detail.html' }); })
事件取消
使用on()
方法綁定事件后,若希望取消綁定,則可以使用off()
方法。 off()
方法根據傳入參數的不同,有不同的實現邏輯。
-
version added: 2.0.0.off( event , selector , handler )
-
version added: 2.0.0.off( event , selector)
-
version added: 2.2.0.off( event )
-
eventType: String需取消綁定的事件名稱,例如:'tap'
-
-
version added: 2.2.0.off( )
-
空參數,刪除該元素上所有事件
-
示例
off(event,selector,handle)
適用於取消對應選擇器上特定事件所執行的特定回調,例如:
//點擊li時,執行foo_1函數 mui("#list").on("tap","li",foo_1); //點擊li時,執行foo_2函數 mui("#list").on("tap","li",foo_2); function foo_1(){ console.log("foo_1 execute"); } function foo_2(){ console.log("foo_2 execute"); } //點擊li時,不再執行foo_1函數,但會繼續執行foo_2函數 mui("#list").off("tap","li",foo_1);
off(event,selector)
適用於取消對應選擇器上特定事件的所有回調,例如:
//點擊li時,執行foo_1函數 mui("#list").on("tap","li",foo_1); //點擊li時,執行foo_2函數 mui("#list").on("tap","li",foo_2); function foo_1(){ console.log("foo_1 execute"); } function foo_2(){ console.log("foo_2 execute"); } //點擊li時,foo_2、foo_2兩個函數均不再執行 mui("#list").off("tap","li");
off(event)
適用於取消當前元素上綁定的特定事件的所有回調,例如:
//點擊li時,執行foo_1函數 mui("#list").on("tap","li",foo_1); //點擊p時,執行foo_3函數 mui("#list").on("tap","p",foo_3); function foo_1(){ console.log("foo_1 execute"); } function foo_3(){ console.log("foo_3 execute"); } //點擊li時,不再執行foo_1函數;點擊p時,也不再執行foo_3函數 mui("#list"
off()
適用於取消當前元素上綁定的所有事件回調,例如:
//點擊li時,執行foo_1函數 mui("#list").on("tap","li",foo_1); //雙擊li時,執行foo_4函數 mui("#list").on("doubletap","li",foo_4); //點擊p時,執行foo_3函數 mui("#list").on("tap","p",foo_3); function foo_1(){ console.log("foo_1 execute"); } function foo_3(){ console.log("foo_3 execute"); } function foo_4(){ console.log("foo_4 execute"); } //點擊li時,不再執行foo_1函數;點擊p時,也不再執行foo_3函數;雙擊li時,也不再執行foo_4函數; mui("#list").off();
事件觸發
使用mui.trigger()
方法可以動態觸發特定DOM元素上的事件。
-
.trigger( element , event , data )
示例
自動觸發按鈕的點擊事件:
var btn = document.getElementById("submit"); //監聽點擊事件 btn.addEventListener("tap",function () { console.log("tap event trigger"); }); //觸發submit按鈕的點擊事件 mui.trigger(btn,'tap');
手勢事件
在開發移動端的應用時,會用到很多的手勢操作,比如滑動、長按等,為了方便開放者快速集成這些手勢,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開關
事件監聽
單個元素上的事件監聽,直接使用addEventListener()
即可,如下:
console.log("你正在向左滑動"); });
若多個元素執行相同邏輯,則建議使用事件綁定(on()
)。
自定義事件
在App開發中,經常會遇到頁面間傳值的需求,比如從新聞列表頁進入詳情頁,需要將新聞id傳遞過去; Html5Plus規范設計了evalJS方法來解決該問題; 但evalJS方法僅接收字符串參數,涉及多個參數時,需要開發人員手動拼字符串; 為簡化開發,mui框架在evalJS方法的基礎上,封裝了自定義事件,通過自定義事件,用戶可以輕松實現多webview間數據傳遞。
僅能在5+ App及流應用中使用
因為是多webview之間傳值,故無法在手機瀏覽器、微信中使用;
監聽自定義事件
添加自定義事件監聽操作和標准js事件監聽類似,可直接通過window對象添加,如下:
window.addEventListener('customEvent',function(event){ //通過event.detail可獲得傳遞過來的參數內容 .... });
觸發自定義事件
通過mui.fire()
方法可觸發目標窗口的自定義事件:
-
.fire( target , event , data )
-
targetType: WebviewObject需傳值的目標webview
-
eventType: String自定義事件名稱
-
dataType: JSONjson格式的數據
-
目標webview必須觸發loaded事件后才能使用自定義事件
若新創建一個webview,不等該webview的loaded事件發生,就立即使用webview.evalJS()或mui.fire(webview,'eventName',{}),則可能無效;案例參考:這里
示例
假設如下場景:從新聞列表頁面進入新聞詳情頁面,新聞詳情頁面為共用頁面,通過傳遞新聞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的utils(工具)
mui的工具和jq很像但是也是有區別的。
init
mui框架將很多功能配置都集中在mui.init方法中,要使用某項功能,只需要在mui.init方法中完成對應參數配置即可,目前支持在mui.init方法中配置的功能包括:創建子頁面、關閉頁面、手勢事件配置、預加載、下拉刷新、上拉加載、設置系統狀態欄背景顏色。
mui需要在頁面加載時初始化很多基礎控件,如監聽返回鍵,因此務必在每個頁面中調用
以下各配置模塊在其對應文檔中有詳細闡述,請點擊鏈接查看,這里只列出所有可配置項
mui.init({ //子頁面 subpages: [{ //... }], //預加載 preloadPages:[ //... ], //下拉刷新、上拉加載 pullRefresh : { //... }, //手勢配置 gestureConfig:{ //... }, //側滑關閉 swipeBack:true, //Boolean(默認false)啟用右滑關閉功能 //監聽Android手機的back、menu按鍵 keyEventBind: { backbutton: false, //Boolean(默認true)關閉back按鍵監聽 menubutton: false //Boolean(默認true)關閉menu按鍵監聽 }, //處理窗口關閉前的業務 beforeback: function() { //... //窗口關閉前處理其他業務詳情點擊 ↑ "關閉頁面"鏈接查看 }, //設置狀態欄顏色 statusBarBackground: '#9defbcg', //設置狀態欄顏色,僅iOS可用 preloadLimit:5//預加載窗口數量限制(一旦超出,先進先出)默認不限制 })
以上各配置模塊在其對應文檔中有詳細闡述,請點擊鏈接查看,以下只補充單獨配置項
通過statusBarBackground:rgb
屬性設置狀態欄顏色(iOS7.0+、安卓不支持)格式為#RRGGBB。
mui.init({ statusBarBackground: '#9defbcg', })
mui默認會監聽Android手機的物理按鍵(back&menu)
,若不希望自動處理按鍵可通過以下方式關閉
mui.init({ //監聽Android手機的back、menu按鍵 keyEventBind: { backbutton: true, //Boolean(默認true)關閉back按鍵監聽 menubutton: true //Boolean(默認true)關閉menu按鍵監聽 }, })
擴展閱讀
代碼塊激活字符:
mui()
mui使用css選擇器獲取HTML元素,返回mui對象數組。mui("p")
:選取所有<p>
元素mui("p.title")
:選取所有包含.title
類的<p>
元素
若要將mui對象轉化成dom對象,可使用如下方法(類似jquery對象轉成dom對象):
//obj1是mui對象 var obj1 = mui("#title"); //obj2是dom對象 var obj2 = obj1[0];
MUI框架的定位是“最接近原生體驗的移動App的UI框架”, 因此和jQuery有所區別,很少為簡化DOM操作而封裝API,具體可參考MUI產品概述; 該函數的設計目的,更多是為了配合MUI插件使用,比如圖片輪播、下拉刷新、區域滾動等,如下為詳細示例:
示例1:跳轉到圖片輪播的第二張圖片
mui('.mui-slider').slider().gotoItem(1);
示例2:重新開啟上拉加載
mui('#pullup-container').pullRefresh().refresh(true);
擴展閱讀
代碼塊激活字符:
each()
each既是一個類方法,同時也是一個對象方法,兩個方法適用場景不同;換言之,你可以使用mui.each()
去遍歷數組或json對象,也可以使用mui(selector).each()
去遍歷DOM結構。
-
mui.each( obj , handler )
-
obj需遍歷的對象或數組;若為對象,僅遍歷對象根節點下的key
-
handler為每個元素執行的回調函數;其中,index表示當前元素的下標或key,element表示當前匹配元素
-
-
mui(selector).each( handler )
-
handler為每個匹配元素執行的回調函數;其中,index表示當前元素在匹配元素中的位置(下標,從0開始),element表示當前匹配元素,可用
this
關鍵字代替
-
示例1
輸出當前數組中每個元素的平方
var array = [1,2,3] mui.each(array,function(index,item){ console.log(item*item); })
示例2
當前頁面中有三個字段,如下:
<div class="mui-input-group"> <div class="mui-input-row"> <label>字段1:</label> <input type="text" class="mui-input-clear" id="col1" placeholder="請輸入"> </div> <div class="mui-input-row"> <label>字段2:</label> <input type="text" class="mui-input-clear" id="col2" placeholder="請輸入"> </div> <div class="mui-input-row"> <label>字段3:</label> <input type="text" class="mui-input-clear" id="col3" placeholder="請輸入"> </div> </div>
提交時校驗三個字段均不能為空,若為空則提醒並終止業務邏輯運行,使用each()
方法循環校驗,如下:
var check = true; mui(".mui-input-group input").each(function () { //若當前input為空,則alert提醒 if(!this.value||trim(this.value)==""){ var label = this.previousElementSibling; mui.alert(label.innerText+"不允許為空"); check = false; return false; } }); //校驗通過,繼續執行業務邏輯 if(check){ //..... }
擴展閱讀
代碼塊激活字符:
extend()
將兩個對象合並成一個對象。
-
.extend( target , object1 [, objectN] )
-
.extend( deep , target , object1 [, objectN] )
示例
var target = { company:"dcloud", product:{ mui:"小巧、高效" } } var obj1 = { city:"beijing", product:{ HBuilder:"飛一樣的編碼" } } mui.extend(target,obj1); //輸出:{"company":"dcloud","product":{"HBuilder":"飛一樣的編碼"},"city":"beijing"} console.log(JSON.stringify(target));
從如上輸出可以看到,product節點下的mui被替換成了HBuilder,因為默認僅合並對象根節點下的key、value;如果想深度合並,則可以傳入deep
參數,如下:
var target = { company:"dcloud", product:{ mui:"小巧、高效" } } var obj1 = { city:"beijing", product:{ HBuilder:"飛一樣的編碼" } } //支持深度合並 mui.extend(true,target,obj1); //輸出:{"company":"dcloud","product":{"mui":"小巧、高效","HBuilder":"飛一樣的編碼"},"city":"beijing"} console.log(JSON.stringify(target));
擴展閱讀
代碼塊激活字符:
later()
setTimeOut封裝
-
.later( func , delay [, context, data] )
擴展閱讀
代碼塊激活字符:
scrollTo()
滾動窗口屏幕到指定位置,該方法是對window.scrollTo()
方法在手機端的增強實現,可設定滾動動畫時間及滾動結束后的回調函數;鑒於手機屏幕大小,該方法僅可實現屏幕縱向滾動。
-
.scrollTo( ypos [, duration] [, handler] )
示例
1秒鍾之內滾動到頁面頂部
mui.scrollTo(0,1000);
擴展閱讀
代碼塊激活字符:
os
我們經常會有通過navigator.userAgent
判斷當前運行環境的需求,mui對此進行了封裝,通過調用mui.os.XXX即可
-
plus(可以訪問的參數為:)
-
.plus返回是否在 5+ App(包括流應用)運行.stream返回是否為流應用
-
-
Android(可以訪問的參數為:)
-
.android返回是否為安卓手機.version安卓版本號.isBadAndroidandroid非Chrome環境
-
-
iOS(可以訪問的參數為:)
-
.ios返回是否為蘋果設備.version返回手機版本號.iphone返回是否為蘋果手機.ipad返回是否為ipad
-
-
Wechat(可以訪問的參數為:)
-
.wechat返回是否在微信中運行
-
示例
檢測是否為iOS或安卓系統版本是否小於4.4
if(mui.os.ios||(mui.os.android&&parseFloat(mui.os.version)<4.4)){ //... }
工具的使用和一般的jq調用很類似也就是方法的區別,可以也是可以很容易就上手的。
五、MUI的AJAX
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( url[, settings])
-
urlType: String請求發送的目標地址
-
settingsType: PlainObjectkey/value格式的json對象,用來配置ajax請求參數,支持的完整參數參考如下
mui.ajax([settings])
方法
-
-
mui.ajax([settings])
-
settingsType: PlainObjectkey/value格式的json對象,用來配置ajax請求參數,支持的詳細參數如下:
-
asyncType: Boolean發送同步請求
-
crossDomain *5+ onlyType: Boolean強制使用5+跨域
-
dataType: PlainObject|| String發送到服務器的業務數據
-
dataTypeType: String預期服務器返回的數據類型;如果不指定,mui將自動根據HTTP包的MIME頭信息自動判斷;支持設置的dataType可選值:
-
"xml": 返回XML文檔
-
"html": 返回純文本HTML信息;
-
"script": 返回純文本JavaScript代碼
-
"json": 返回JSON數據
-
"text": 返回純文本字符串
-
-
errorType: Functon(XMLHttpRequest xhr,String type,String errorThrown)請求失敗時觸發的回調函數,該函數接收三個參數:
- xhr:xhr實例對象
- type:錯誤描述,可取值:"timeout", "error", "abort", "parsererror"、"null"
- errorThrown:可捕獲的異常對象
-
successType: Functon(Anything data,String textStatus,XMLHttpRequest xhr)請求成功時觸發的回調函數,該函數接收三個參數:
- data:服務器返回的響應數據,類型可以是json對象、xml對象、字符串等;
- textStatus:狀態描述,默認值為'success'
- xhr:xhr實例對象
-
timeoutType: Number請求超時時間(毫秒),默認值為0,表示永不超時;若超過設置的超時時間(非0的情況),依然未收到服務器響應,則觸發error回調
-
typeType: String請求方式,目前僅支持'GET'和'POST',默認為'GET'方式
-
headersType: Json指定HTTP請求的Header
headers:{'Content-Type':'application/json'}
-
processDataType: Boolean為了匹配默認的
content-type("application/x-www-form-urlencoded")
,
mui默認會將data
參數中傳入的非字符串類型的數據轉變為key1=value&key2=value2
格式的查詢串;
如果業務需要,希望發送其它格式的數據(比如Document對象),可以設置processData
為false
-
-
代碼示例:如下為通過post方式向某服務器發送鑒權登錄的代碼片段
mui.ajax('http://server-name/login.php',{ data:{ username:'username', password:'password' }, dataType:'json',//服務器返回json格式數據 type:'post',//HTTP請求類型 timeout:10000,//超時時間設置為10秒; headers:{'Content-Type':'application/json'}, 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的下拉刷新
概述
為實現下拉刷新功能,大多數 H5 框架都是通過 DIV 模擬下拉回彈動畫,在低端 android 手機上,DIV 動畫經常出現卡頓現象(特別是圖文列表的情況); mui 通過使用原生 webview 下拉刷新解決這個 DIV 動畫的卡頓問題,並且拖動效果更加流暢;
這里提供兩種模式的下拉刷新,以適用不同場景:
單 webview 模式
-
效果展示:
-
動畫原理:
下拉刷新時,觸發的是原生下拉刷新控件,而整個
webview
位置不會發生變化,所以不會在拖動過程中發生DOM重繪,當控件拖動到一定位置觸發動態加載數據以及刷新操作。此模式下拉刷新,相比雙webview 模式,不創建額外 webview,性能更優。 -
使用方法:
mui 初始化時設置
pullRefresh
各項參數,與雙 webview 模式的子頁面設置是一樣的。說明:- DOM結構無特殊要求,只需要指定一個下拉刷新容器標識即可
mui.init({ pullRefresh : { container:"#refreshContainer",//下拉刷新容器標識,querySelector能定位的css選擇器均可,比如:id、.class等 down : { style:'circle',//必選,下拉刷新樣式,目前支持原生5+ ‘circle’ 樣式 color:'#2BD009', //可選,默認“#2BD009” 下拉刷新控件顏色 height:'50px',//可選,默認50px.下拉刷新控件的高度, range:'100px', //可選 默認100px,控件可下拉拖拽的范圍 offset:'0px', //可選 默認0px,下拉刷新控件的起始位置 auto: true,//可選,默認false.首次加載自動上拉刷新一次 callback :pullfresh-function //必選,刷新函數,根據具體業務來編寫,比如通過ajax從服務器獲取新數據; } } });
-
模式說明:
- 優點:
- 性能更優,體現在兩點:
- 相比雙webview,不創建額外子 webview 性能消耗更少
- 下拉拖動過程中不會發生重繪,也減少了性能消耗
- 性能更優,體現在兩點:
- 缺點:
- 目前僅支持‘cricle’樣式以及該樣式的顏色自定義
- 優點:
雙 webview 模式
-
效果展示:
-
動畫原理:
使用雙 webview 模式的下拉刷新,創建一個子 webview 添加列表;拖動時,拖動的是一個完整的 webview,避免了類似 DIV 拖動流暢度不好的問題,回彈動畫使用原生動畫;在 iOS 平台,H5 的動畫已經比較流暢,故依然使用 H5 方案。兩個平台實現雖有差異,但 mui 經過封裝,可使用一套代碼實現下拉刷新。
-
使用方法:
主頁面內容比較簡單,只需要創建子頁面即可:
mui.init({ subpages:[{ url:pullrefresh-subpage-url,//下拉刷新內容頁面地址 id:pullrefresh-subpage-id,//內容頁面標志 styles:{ top:subpage-top-position,//內容頁面頂部位置,需根據實際頁面布局計算,若使用標准mui導航,頂部默認為48px; .....//其它參數定義 } }] });
iOS平台的下拉刷新,使用的是 mui 封裝的區域滾動組件, 為保證兩個平台的 DOM 結構一致,內容頁面需統一按照如下 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 : { height:50,//可選,默認50.觸發下拉刷新拖動距離, auto: true,//可選,默認false.首次加載自動下拉刷新一次 contentdown : "下拉可以刷新",//可選,在下拉可刷新狀態時,下拉刷新控件上顯示的標題內容 contentover : "釋放立即刷新",//可選,在釋放可刷新狀態時,下拉刷新控件上顯示的標題內容 contentrefresh : "正在刷新...",//可選,正在刷新狀態時,下拉刷新控件上顯示的標題內容 callback :pullfresh-function //必選,刷新函數,根據具體業務來編寫,比如通過ajax從服務器獲取新數據; } } });
-
模式說明:
- 優點:
- 可自定義下拉刷新樣式,更改文字等等.參考關於自定義下拉刷新樣式問答
- 缺點:
- 相比單 webview,性能消耗更大,不過都比 div 模式的要好用
- DOM結構需要統一配置
- 優點:
-
滾動到特定位置
下拉刷新組件滾動到特定位置的方法類似區域滾動組件
目前僅支持 雙 webview 模式
-
scrollTo( xpos , ypos [, duration] )
示例:在 hello mui 下拉刷新示例中,實現了雙擊標題欄,讓列表快速回滾到頂部的功能;代碼如下:
var contentWebview = null; //監聽標題欄的雙擊事件 document.querySelector('header').addEventListener('doubletap',function () { if(contentWebview==null){ contentWebview = plus.webview.currentWebview().children()[0]; } //內容區滾動到頂部 contentWebview.evalJS("mui('#pullrefresh').pullRefresh().scrollTo(0,0,100)"); });
-
-
更改下拉刷新文字位置
*可以解決修改下拉刷新子頁面默認
top
值后,下拉刷新提示框位置異常問題根據實際需求在父頁面給mui-content設置top屬性
目前僅支持 雙 webview 模式
.mui-bar-nav ~ .mui-content .mui-pull-top-pocket{ top: 180px !important; }
自動觸發下拉刷新
mui 支持設置首次加載時自動觸發一次下拉刷新,配置如下auto
參數為:true
即可,上拉加載同樣支持此配置
mui.init({ pullRefresh : { container:"#refreshContainer",//下拉刷新容器標識,querySelector能定位的css選擇器均可,比如:id、.class等 down : { auto: true,//可選,默認false.首次加載自動下拉刷新一次 }, up : { auto: true //可選,默認false.首次加載自動上拉加載一次 } } });
下拉刷新結束
兩種模式在下拉刷新過程中,當獲取新數據后,都需要執行 endPulldown
方法, 該方法的作用是關閉“正在刷新”的樣式提示,內容區域回滾頂部位置,如下:
function pullfresh-function() { //業務邏輯代碼,比如通過ajax從服務器獲取新數據; ...... //注意,加載完新數據后,必須執行如下代碼,注意:若為ajax請求,則需將如下代碼放置在處理完ajax響應數據之后 //沒有更多內容了,endPulldown 傳入true, 不再執行下拉刷新 mui('#refreshContainer').pullRefresh().endPulldown(); }
七、MUI的上拉加載
概述
mui的上拉加載和下拉刷新類似,都屬於pullRefresh
插件,使用過程如下:
- 1、頁面滾動到底,顯示“正在加載...”提示(mui框架提供)
- 2、執行加載業務數據邏輯(開發者提供)
- 3、加載完畢,隱藏"正在加載"提示(mui框架提供)
開發者只需關心業務邏輯,實現加載更多數據即可。
初始化
初始化方法類似下拉刷新,通過mui.init方法中pullRefresh參數配置上拉加載各項參數,如下:
mui.init({ pullRefresh : { container:refreshContainer,//待刷新區域標識,querySelector能定位的css選擇器均可,比如:id、.class等 up : { height:50,//可選.默認50.觸發上拉加載拖動距離 auto:true,//可選,默認false.自動上拉加載一次 contentrefresh : "正在加載...",//可選,正在加載狀態時,上拉加載控件上顯示的標題內容 contentnomore:'沒有更多數據了',//可選,請求完畢若沒有更多數據時顯示的提醒內容; callback :pullfresh-function //必選,刷新函數,根據具體業務來編寫,比如通過ajax從服務器獲取新數據; } } });
結束上拉加載
加載完新數據后,需要執行endPullupToRefresh()方法,結束轉雪花進度條的“正在加載...”過程
-
.endPullupToRefresh( nomore )
-
nomoreType: Boolean是否還有更多數據;若還有更多數據,則傳入false; 否則傳入true,之后滾動條滾動到底時,將不再顯示“上拉顯示更多”的提示語,而顯示“沒有更多數據了”的提示語;
-
示例:
function pullfresh-function() { //業務邏輯代碼,比如通過ajax從服務器獲取新數據; ...... //注意: //1、加載完新數據后,必須執行如下代碼,true表示沒有更多數據了: //2、若為ajax請求,則需將如下代碼放置在處理完ajax響應數據之后 this.endPullupToRefresh(true|false); }
重置上拉加載
若部分業務中,有重新觸發上拉加載的需求(比如當前類別已無更多數據,但切換到另外一個類別后,應支持繼續上拉加載),此時調用.refresh(true)
方法,可重置上拉加載控件,如下代碼:
//pullup-container為在mui.init方法中配置的pullRefresh節點中的container參數; //注意:refresh()中需傳入true mui('#pullup-container').pullRefresh().refresh(true);
禁用上拉刷新
在部分場景下希望禁用上拉加載,比如在列表數據過少時,不想顯示“上拉顯示更多”、“沒有更多數據”的提示語,開發者可以通過調用disablePullupToRefresh()
方法實現類似需求,代碼如下:
//pullup-container為在mui.init方法中配置的pullRefresh節點中的container參數; mui('#pullup-container').pullRefresh().disablePullupToRefresh();
啟用上拉刷新
使用disablePullupToRefresh()
方法禁用上拉加載后,可通過enablePullupToRefresh()
方法再次啟用上拉加載,代碼如下:
//pullup-container為在mui.init方法中配置的pullRefresh節點中的container參數; mui('#pullup-container').pullRefresh().enablePullupToRefresh();
八、MUI的代碼塊
MUI的代碼塊有js代碼塊,有html的代碼塊詳情看看我發給你們的鏈接。
下面我們進入開發階段,第一步可以上官網拷貝下來一個demo,打開HBuilder新建一個移動APP項目,選擇MUI框架,粘貼你的代碼運行即可。
部分mui控件監聽的事件無法通過
mui.trigger
觸發比如無法實現自動觸發mui返回圖標,實現關閉當前頁面的功能,該部分邏輯正在優化中