# 寫在前面
> 本系列文章我們將利用mui基于網易云音樂API實現一個音樂播放器APP,同時基于環形或者融云實現聊天功能。作為本系列文章的第一篇,本文會詳細講解html5+中管理應用窗口界面的Webview模塊的用法,因為是初級教程篇不過多講解原理部分,初級用戶只需要知道基本用法就可以,并使用mui.js中的組件進行頁面效果展示。
# webview基本知識
> Webview模塊管理應用窗口界面,實現多窗口的邏輯控制管理操作。通過plus.webview可獲取應用界面管理對象。
# 什么是窗口?什么是webview?
> 這里我們首先來舉個例子,大家都用過瀏覽器,常用的瀏覽器可以打開多個網頁。電腦屏幕就是一個窗口,不同的頁面我們可以什么是不同的webview,我們可以通過控制webview的切換從而控制瀏覽不同的頁面。
> 對于我們這里就是一個html頁面就是一個窗口,一個html頁面可以創建多個webview。這個webview是原生APP中瀏覽網頁的組件,android和iOS都有,html5plus中的webview是對原生webview的封裝,可以用js進行調用,所以它的運行環境是APP環境,普通瀏覽器不支持。
> 首先我們現在html5plus官網看一下webview API文檔,這里我們重點看一下下面幾個方法:
# 創建新的Webview窗口
~~~
WebviewObject plus.webview.create( url, id, styles, extras );
~~~
### 說明:
創建Webview窗口,用于加載新的HTML頁面,可通過styles設置Webview窗口的樣式,創建完成后需要調用show方法才能將Webview窗口顯示出來。
# 顯示Webview窗口
~~~
void plus.webview.show( id_wvobj, aniShow, duration, showedCB, extras );
~~~
### 說明:
顯示已創建或隱藏的Webview窗口,需先獲取窗口對象或窗口id,并可指定顯示窗口的動畫及動畫持續時間。
# 隱藏Webview窗口
~~~
void plus.webview.hide( id_wvobj, aniHide, duration, extras );
~~~
### 說明:
根據指定的WebviewObject對象或id隱藏Webview窗口,使得窗口不可見。
# 獲取當前窗口的WebviewObject對象
~~~
WebviewObject plus.webview.currentWebview();
~~~
### 說明:
獲取當前頁面所屬的Webview窗口對象。
# 查找指定標識的WebviewObject窗口
~~~
WebviewObject plus.webview.getWebviewById( id );
~~~
### 說明:
在已創建的窗口列表中查找指定標識的Webview窗口并返回。 若沒有查找到指定標識的窗口則返回null,若存在多個相同標識的Webview窗口,則返回第一個創建的Webview窗口。 如果要獲取應用入口頁面所屬的Webview窗口,其標識為應用的%APPID%,可通過plus.runtime.appid獲取。
# 創建并打開Webview窗口
~~~
WebviewObject plus.webview.open( url, id, styles, aniShow, duration, showedCB );
~~~
### 說明:
創建并顯示Webview窗口,用于加載新的HTML頁面,可通過styles設置Webview窗口的樣式,創建完成后自動將Webview窗口顯示出來。
以上來源于html5plus文檔,只列舉了部分最常用的方法,旨在為后文做鋪墊,由于不是文檔,所以也得也不清楚,如果想詳細了解請看這里html5plus webview API。
mui雙webview模式
首先我們要了解mui為了解決窗體切換白屏和區域滾動提出的雙webview模式。
## 頁面初始化
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(默認truee)關閉back按鍵監聽
menubutton: false //Boolean(默認true)關閉menu按鍵監聽
},
//處理窗口關閉前的業務
beforeback: function() {
//... //窗口關閉前處理其他業務詳情點擊 ↑ "關閉頁面"鏈接查看
},
//設置狀態欄顏色
statusBarBackground: '#9defbcg', //設置狀態欄顏色,僅iOS可用
preloadLimit:5//預加載窗口數量限制(一旦超出,先進先出)默認不限制
})
~~~
在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顯示具體列表內容,列表項的滾動是在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,可不定義;
}
}]
});
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只會增加新的執行邏輯,老的監聽邏輯依然會執行;
# 項目實戰
這個系列的教程我準備帶大家一起實現音樂播放器和即時通訊的功能,先上圖不多說:

開始的頁面效果很簡單,就是一個tab bar頁面切換組件,我們重點講解實現方法,至于美化是后面的事。在開始項目之前我先抄了文檔的內容,不是為了湊內容,只是想讓新手在開始項目之前還是多看看基本概念,俗話說磨刀不誤砍柴工,我們對mui的設計思路有一定了解之后寫起來才能得心應手。
相信大家對于mui的雙webview模式有初步認識,我們可以分析一下我們接下來要做的這個的實際例子,首先我們的入口文件index.html是一個包括頭部和底部的導航欄的webview,中間是一個動態的webview,我們通過點擊底部導航欄進行頁面切換,并且動態的改變頂部導航欄的內容。
### 下面我們新建一個mui項目,這里我命名為M-BOX:
點擊【文件】=》【新建】=》【移動APP】
設置應用名稱、文件存儲路徑、選擇模板

js,css,fonts文件的詳細介紹請戳這里手把手教你開發HelloWord
HBuilder對前端代碼的調試方式這個是很重要的一個部分,限于篇幅,這里不能講解,請自己看教程。
開始寫布局文件
相信很多人看了前面那么多文檔介紹內心肯定是崩潰的,其實我也是,畢竟寫了那么多還沒有開始寫代碼我也是拒絕的,只是考慮到很多新手對于找文檔這事不一定有經驗,那還是先貼一下,大不了回過頭再去看咯。
好,那我們開始寫布局文件:
在MUI開發注意事項這篇文章中提到了幾個重要的注意事項,我們在一個就注意一下會比較好,這里不再一一詳細列舉了,讀者自己去看。
文章中DOM結構提到:
固定欄靠前
所謂的固定欄,也就是帶有.mui-bar屬性的節點,都是基于fixed定位的元素;常見組件包括:頂部導航欄(.mui-bar-nav)、底部工具條(.mui-bar-footer)、底部選項卡(.mui-bar-tab);這些元素使用時需遵循一個規則:放在.mui-content元素之前,即使是底部工具條和底部選項卡,也要放在.mui-content之前,否則固定欄會遮住部分主內容;
一切內容都要包裹在mui-content中
除了固定欄之外,其它內容都要包裹在.mui-content中,否則就有可能被固定欄遮罩,原因:固定欄基于Fixed定位,不受流式布局限制,普通內容依然會從top:0的位置開始布局,這樣就會被固定欄遮罩,mui為了解決這個問題,定義了如下css代碼:
~~~
.mui-bar-nav ~ .mui-content {
padding-top: 44px;
}
.mui-bar-footer ~ .mui-content {
padding-bottom: 44px;
}
.mui-bar-tab ~ .mui-content {
padding-bottom: 50px;
}
~~~
我們這里重點看這兩條規則,因為這個對于我們正確布局是至關重要的。
下面我們體驗一下hbuilder的代碼塊功能,在index.html文件的body之間輸入mheader,回車試試。
哈哈,頁面頭部出來了,不錯,這里我們然后刪除下面的:
~~~
<a class="mui-action-back mui-icon mui-icon-left-nav mui-pull-left"></a>
~~~
### 先去掉返回箭頭。
然后繼續輸入mtab,回車,底部導航欄也出來了,我們修改一下導航欄的內容,把代碼稍微調整一下。
整體代碼如下:
~~~
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
<title>M-BOX</title>
<link href="css/mui.min.css" rel="stylesheet"/>
</head>
<body>
<header class="mui-bar mui-bar-nav">
<h1 class="mui-title">標題</h1>
</header>
<nav class="mui-bar mui-bar-tab">
<a class="mui-tab-item mui-active">
<span class="mui-icon mui-icon-home"></span>
<span class="mui-tab-label">首頁</span>
</a>
<a class="mui-tab-item">
<span class="mui-icon mui-icon-chatboxes"></span>
<span class="mui-tab-label">消息</span>
</a>
<a class="mui-tab-item">
<span class="mui-icon mui-icon-gear"></span>
<span class="mui-tab-label">設置</span>
</a>
</nav>
<script src="js/mui.min.js"></script>;
<script type="text/javascript" charset="utf-8">
mui.init() //初始化
</script>
</body>
</html>
~~~
首頁的靜態布局我們寫完了,我們接下來新建三個含mui的html文件:
選擇工程名,郵件就可以看到【新建】,然后就是選擇【目錄】新建文件夾和【html文件】新建含mui的html文件。我們新建一個文件夾html,并且在html文件夾下新建,home.html,message.html,setting.html。
在三個頁面body之間分別輸入mbody,就可以開始分別寫頁面了,比如可以先在頁面上寫上文件名,我們先來完善首頁的子頁切換邏輯。
動態頁面切換
### 1.創建子頁面,首個選項卡頁面顯示,其它均隱藏;
主要方法就是用plus.webview.create和plus.webview.hide();
~~~
//設置默認打開首頁顯示的子頁序號;
var Index=0;
//把子頁的路徑寫在數組里面
var subpages = ['html/home.html','html/message.html','html/setting.html'];
//所有的plus-*方法寫在mui.plusReady中或者后面。
mui.plusReady(function() {
//獲取當前頁面所屬的Webview窗口對象
var self = plus.webview.currentWebview();
for (var i = 0; i < 3; i++) {
//創建webview子頁
var sub = plus.webview.create(
subpages[i], //子頁url
subpages[i], //子頁id
{
top: '45px',//設置距離頂部的距離
bottom: '50px'//設置距離底部的距離
}
);
//如不是我們設置的默認的子頁則隱藏,否則添加到窗口中
if (i != Index) {
sub.hide();
}
//將webview對象填充到窗口
self.append(sub);
}
});
~~~
注:如果Index不是0,需要將nav下的a標簽中的.mui-active屬性寫到對應的a標簽下。
執行完我們會發現home.html的內容顯示出來了,但是底部切換還不能,因為這里我們還沒有監聽底部的點擊事件。在進行下一步之前,我們可以先做一個小實驗,將上面的代碼中的top或者bottom改為0,我們會發現,底部欄或者底部欄會被覆蓋,這是因為mui一個重要的潛規則,父子結構的頁面子頁面會比父頁面層級高,說白了就是子頁面可以蓋住父頁面。這會導致開發者常犯的一個錯誤:將彈出層或者彈出菜單寫在父頁面被子頁面蓋住的bug。
這里的apend()方法在html5plus文檔中沒有提到,這里的這個方法是將webview對象填充到窗口的方法。
# 2.選項卡點擊事件
mui 內部封裝了一些常用的方法,其中DOM選擇器、事件綁定等事件管理。具體可以參考文檔:選擇器、事件管理。
~~~
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];
.on( event , selector , handler )
event
Type: String
需監聽的事件名稱,例如:’tap’
selector
Type: String
-選擇器
handler
Type: Function( Event event )
事件觸發時的回調函數,通過回調中的event參數可以獲得事件詳情
除了可以使用addEventListener()方法監聽某個特定元素上的事件外, 也可以使用.on()方法實現批量元素的事件綁定。
~~~
這里我們將為底部導航按鈕添加事件:
~~~
//選項卡點擊事件
mui('.mui-bar-tab').on('tap', 'a', function(e) {
alert(true);
});
~~~
當我們點擊底部選項卡的時候會彈出true,這不夠,我們要能夠分辨當前對象具體是哪一個,有兩種思路:
第一我們能夠知道當前點擊的a標簽所在序號就好了,就是找到index,然后根據上面那個subpages數組,利用plus.webview.show(subpages[index])方法顯示。
我們給當前點擊的a標簽添加一個可以識別的屬性,然后根據那個屬性獲取當前a的特征,然后就可以顯示點擊的子頁,隱藏當前子頁。
第一種方法需要遍歷此案獲取index,第二種方法添加一個href很容易拿到子頁id,我們采用第二種方案。
getAttribute()
getAttribute() 方法返回指定屬性名的屬性值。
提示:如果您希望以 Attr 對象返回屬性,請使用 getAttributeNode。
于是我們可以這樣寫:
~~~
//當前激活選項
var activeTab = subpages[Index],title=document.querySelector(".mui-title");
//選項卡點擊事件
mui('.mui-bar-tab').on('tap', 'a', function(e) {
//獲取目標子頁的id
var targetTab = this.getAttribute('href');
if (targetTab == activeTab) {
return;
}
//更換標題
title.innerHTML = this.querySelector('.mui-tab-label').innerHTML;
//顯示目標選項卡
plus.webview.show(targetTab);
//隱藏當前選項卡
plus.webview.hide(activeTab);
//更改當前活躍的選項卡
activeTab = targetTab;
});
~~~
# 兼容瀏覽器的處理辦法
這是6月29號補充的內容,最開始寫的時候沒有這個內容,在這里加上吧。為啥要加這個內容呢,因為發現很多人思維還是比較局限,用mui依然還是用原來的方法,有很多人依然使用href,之所以這么用就是大家改不了習慣,這就是被很多人說的坑。。。但是真的是坑嗎?與其說是坑,我覺得是大家思維上沒有轉變過來,不明白mui為啥要禁用href這種方式,也不明白自己該怎么做。
下面貼出一個用iframe代替多子webview形式的tabbar在瀏覽器的兼容處理方法:
~~~
var createIframe = function (el, opt) {
var elContainer = document.querySelector(el);
var wrapper = document.querySelector(".mui-iframe-wrapper");
if(!wrapper){
// 創建wrapper 和 iframe
wrapper = document.createElement('div');
wrapper.className = 'mui-iframe-wrapper';
for(var i in opt.style){
wrapper.style[i] = opt.style[i];
}
var iframe = document.createElement('iframe');
iframe.src = opt.url;
iframe.id = opt.id || opt.url;
iframe.name = opt.id;
wrapper.appendChild(iframe);
elContainer.appendChild(wrapper);
}else{
var iframe = wrapper.querySelector('iframe');
iframe.src = opt.url;
iframe.id = opt.id || opt.url;
iframe.name = iframe.id;
}
}
~~~
### 調用也很簡單:
~~~
//當前激活選項
var activeTab = subpages[Index],title=document.querySelector(".mui-title");
mui('.mui-bar-tab').on('tap', 'a', function(e) {
// 獲取目標子頁的id
var targetTab = this.getAttribute('href');
if (targetTab == activeTab) {
return;
}
// 更換標題
title.innerHTML = this.querySelector('.mui-tab-label').innerHTML;
// 子頁內容切換
if(mui.os.plus){
// 顯示目標webview
plus.webview.show(targetTab);
// 隱藏當前webview
plus.webview.hide(activeTab);
// 更改當前活躍的選項卡
activeTab = targetTab;
}else{
// 創建iframe代替子頁面
createIframe('.mui-content',{
url: targetTab,
style: {
top: '45px',//設置距離頂部的距離
bottom: '50px'//設置距離底部的距離
}
});
}
})
~~~
這樣你就可以一套代碼實現在多平臺的利用啦,是不是很棒。
### 后記
雖然最后實現的效果很簡單,好像直接看demo就可以寫出來,但是新手甚至寫了一段時間的同學也不見得對webview掌握得很好,這篇文章花了很長的篇幅去講解webview的用法,旨在為新手建立一種學習mui這邊的思路,那就是先看html5plus里面的模塊,然后看mui對應的文檔,最后看hello mui的demo,把握這種學習路線個人覺得是一種最佳的方案。本文作為系列文章第一篇講代碼的,所以做了很多鋪墊,所以有一定基礎的同學可能會覺得寫得并沒有什么看點,后面的肯定會有所不一樣的。下一篇講解的是網絡請求XMLHttpRequest模塊,下一講會結合mui.ajax和網易云音樂API一起講解。
- mui
- 拓展
- 本地存儲
- 獲取時間
- 滾動幀聽
- ui組件
- accordion(折疊面板)
- actionsheet(操作表)
- badge(數字角標)
- button(按鈕)
- cardview(卡片視圖)
- checkbox(復選框)
- dialog(對話框)
- 圖片輪播
- 輸入增強
- list(列表)
- 遮罩蒙版
- media list(圖文列表)
- numbox(數字輸入框)
- 側滑導航
- 彈出菜單
- picker(選擇器)
- popPicker
- dtpicker
- progressbar(滾動條)
- radio(單選框)
- range(滑塊)
- scroll(區域滾動)
- slide(輪播組件)
- switch(開關)
- 手機底層
- 蜂鳴提示音和手機震動
- 設備信息
- 手機信息
- 電話
- 發送短信
- 消息框
- 瀏覽器打開網頁
- 界面
- 手勢
- 輪播組件
- 底部導航
- 打開新頁面
- 遮罩
- webview詳解
- js基礎
- 數組
- mui教程
- 教程— html5+ webview 底部欄用法詳解(二)(轉載)
- 自動彈出虛擬鍵盤
- Native.js示例匯總