溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

web app教程:MUI學(xué)習(xí)筆記第二課:頁(yè)面布局

發(fā)布時(shí)間:2020-05-31 10:03:14 來源:網(wǎng)絡(luò) 閱讀:881 作者:netroc2015 欄目:移動(dòng)開發(fā)

頁(yè)面初始化

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

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

mui.init()    mui插件初始化

創(chuàng)建子頁(yè)面

在mobile app開發(fā)過程中,經(jīng)常遇到卡頭卡尾的頁(yè)面,此時(shí)若使用局部滾動(dòng),在android手機(jī)上會(huì)出現(xiàn)滾動(dòng)不流暢的問題; mui的解決思路是:將需要滾動(dòng)的區(qū)域通過單獨(dú)的webview實(shí)現(xiàn),完全使用原生滾動(dòng)。具體做法則是:將目標(biāo)頁(yè)面分解為主頁(yè)面和內(nèi)容頁(yè)面,主頁(yè)面顯示卡 頭卡尾區(qū)域,比如頂部導(dǎo)航、底部選項(xiàng)卡等;內(nèi)容頁(yè)面顯示具體需要滾動(dòng)的內(nèi)容,然后在主頁(yè)面中調(diào)用mui.init方法初始化內(nèi)容頁(yè)面。

mui.init({
    subpages:[{
      url:your-subpage-url,//子頁(yè)面HTML地址,支持本地地址和網(wǎng)絡(luò)地址
      id:your-subpage-id,//子頁(yè)面標(biāo)志
      styles:{
        top:subpage-top-position,//子頁(yè)面頂部位置
        bottom:subpage-bottom-position,//子頁(yè)面底部位置
        width:subpage-width,//子頁(yè)面寬度,默認(rèn)為100%
        height:subpage-height,//子頁(yè)面高度,默認(rèn)為100%
        ......
      },
      extras:{}//額外擴(kuò)展參數(shù)
    }]
  });

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

示例:Hello mui的首頁(yè)其實(shí)就是index.html加list.html合并而成的,如下:

web app教程:MUI學(xué)習(xí)筆記第二課:頁(yè)面布局          

index.html

+

web app教程:MUI學(xué)習(xí)筆記第二課:頁(yè)面布局          

list.html

=

web app教程:MUI學(xué)習(xí)筆記第二課:頁(yè)面布局        

合并后的首頁(yè)

index.html 的作用就是顯示固定導(dǎo)航,list.html顯示具體列表內(nèi)容,列表項(xiàng)的滾動(dòng)是在list.html所在webview中使用原生滾動(dòng),既保證了滾動(dòng)條不 會(huì)穿透頂部導(dǎo)航,符合app的體驗(yàn),也保證了列表流暢滾動(dòng),解決了區(qū)域滾動(dòng)卡頓的問題。 list.html就是index.html的子頁(yè)面,創(chuàng)建代碼比較簡(jiǎn)單,如下:

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

打開新頁(yè)面

做web app,一個(gè)無法避開的問題就是轉(zhuǎn)場(chǎng)動(dòng)畫;web是基于鏈接構(gòu)建的,從一個(gè)頁(yè)面點(diǎn)擊鏈接跳轉(zhuǎn)到另一個(gè)頁(yè)面,如果通過有刷新的打開方式,用戶要面對(duì)一個(gè)空白 的頁(yè)面等待;如果通過無刷新的方式,用Javascript移入DOM節(jié)點(diǎn)(常見的SPA解決方案),會(huì)碰到很高的性能挑戰(zhàn):DOM節(jié)點(diǎn)繁多,頁(yè)面太大, 轉(zhuǎn)場(chǎng)動(dòng)畫不流暢甚至導(dǎo)致瀏覽器崩潰; mui的解決思路是:?jiǎn)蝫ebview只承載單個(gè)頁(yè)面的dom,減少dom層級(jí)及頁(yè)面大?。豁?yè)面切換使用原生動(dòng)畫,將最耗性能的部分交給原生實(shí)現(xiàn).

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

參數(shù)說明:

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

  • extras:新窗口的額外擴(kuò)展參數(shù),可用來處理頁(yè)面間傳值;例如:var webview = mui.openWindow({url:'info.html',extras:{name:'mui'}});console.log(webview.name);,會(huì)輸出"mui"字符串;注意:擴(kuò)展參數(shù)僅在打開新窗口時(shí)有效,若目標(biāo)窗口為預(yù)加載頁(yè)面,則通過mui.openWindow方法打開時(shí)傳遞的extras參數(shù)無效。

  • createNew:是否重復(fù)創(chuàng)建相同id的webview;為優(yōu)化性能、避免app中重復(fù)創(chuàng)建webview,mui v1.7.0開始增加createNew參數(shù),默認(rèn)為false;判斷邏輯如下:若createNew為true,則不判斷重復(fù),每次都新建 webview;若為fasle,則先計(jì)算當(dāng)前App中是否已存在同樣id的webview,若存在則直接顯示;否則新創(chuàng)建并根據(jù)show參數(shù)執(zhí)行顯示邏 輯;該參數(shù)可能導(dǎo)致的影響:若業(yè)務(wù)寫在plusReady事件中,而plusReady事件僅首次創(chuàng)建時(shí)會(huì)觸發(fā),則下次再次通過mui.openWindow方法打開同樣webview時(shí),是不會(huì)再次觸發(fā)plusReady事件的,此時(shí)可通過自定義事件觸發(fā);案例參考:http://ask.dcloud.net.cn/question/6514;

  • show表示窗口顯示控制。autoShow:目標(biāo)窗口loaded事件發(fā)生后,是否自動(dòng)顯示;若目標(biāo)頁(yè)面為預(yù)加載頁(yè)面,則該參數(shù)無效;aniShow表示頁(yè)面顯示動(dòng)畫,比如從右側(cè)劃入、從下側(cè)劃入等,具體可參考5+規(guī)范中的AnimationTypeShow

  • waiting表示系統(tǒng)等待框;mui框架在打開新頁(yè)面時(shí)等待框的處理邏輯為:顯示等待框-->創(chuàng)建目標(biāo)頁(yè)面 webview-->目標(biāo)頁(yè)面loaded事件發(fā)生-->關(guān)閉等待框;因此,只有當(dāng)新頁(yè)面為新創(chuàng)建頁(yè)面(webview)時(shí),會(huì)顯示等待框, 否則若為預(yù)加載好的頁(yè)面,則直接顯示目標(biāo)頁(yè)面,不會(huì)顯示等待框。waiting中的參數(shù):autoShow表示自動(dòng)顯示等待框,默認(rèn)為true,若為 false,則不顯示等待框;注意:若顯示了等待框,但目標(biāo)頁(yè)面不自動(dòng)顯示,則需在目標(biāo)頁(yè)面中通過如下代碼關(guān)閉等待框plus.nativeUI.closeWaiting();。title表示等待框上的提示文字,options表示等待框顯示參數(shù),比如寬高、背景色、提示文字顏色等,具體可參考5+規(guī)范中的WaitingOption。

示例1:Hello mui中,點(diǎn)擊首頁(yè)右上角的圖標(biāo),會(huì)打開關(guān)于頁(yè)面,實(shí)現(xiàn)代碼如下:

//tap為mui封裝的單擊事件,可參考手勢(shì)事件章節(jié)document.getElementById('info').addEventListener('tap', function() {
  //打開關(guān)于頁(yè)面
  mui.openWindow({
    url: 'examples/info.html', 
    id:'info'
  });});

因沒有傳入styles參數(shù),故默認(rèn)全屏顯示;也沒有傳入show參數(shù),故使用slide-in-right動(dòng)畫,新頁(yè)面從右側(cè)滑入。

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

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

第二步,在B頁(yè)面獲取列表數(shù)據(jù)后,再關(guān)閉等待框、顯示B頁(yè)面

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

關(guān)閉頁(yè)面

mui框架將窗口關(guān)閉功能封裝在mui.back方法中,具體執(zhí)行邏輯是:

  • 若當(dāng)前webview為預(yù)加載頁(yè)面,則hide當(dāng)前webview;

  • 否則,close當(dāng)前webview;

在mui框架中,有三種操作會(huì)觸發(fā)頁(yè)面關(guān)閉(執(zhí)行mui.back方法):

  • 點(diǎn)擊包含.mui-action-back類的控件

  • 在屏幕內(nèi),向右快速滑動(dòng)

  • Android手機(jī)按下back按鍵

iOS平臺(tái)原生支持從屏幕邊緣右滑關(guān)閉

iOS平臺(tái)可通過popGesture參數(shù)實(shí)現(xiàn)從屏幕邊緣右滑關(guān)閉webview,參考5+規(guī)范,若想禁用該功能,可通過setStyle方法設(shè)置popGesture為none。

 

hbuilder中敲mheader生成的代碼塊,會(huì)自動(dòng)生成帶有返回導(dǎo)航箭頭的標(biāo)題欄,點(diǎn)擊返回箭頭可關(guān)閉當(dāng)前頁(yè)面,原因就是因?yàn)樵摲祷丶^包含.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>
	<h2 class="mui-title">標(biāo)題</h2></header>
 

若希望在頂部導(dǎo)航欄之外的其它區(qū)域添加關(guān)閉頁(yè)面的控件,只需要在對(duì)應(yīng)控件上添加.mui-action-back類即可,如下為一個(gè)關(guān)閉按鈕示例:

<button type="button" class='mui-btn mui-btn-danger mui-action-back'>關(guān)閉</button>

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

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

mui框架默認(rèn)會(huì)監(jiān)聽Android手機(jī)的back按鍵,然后執(zhí)行頁(yè)面關(guān)閉邏輯; 若不希望mui自動(dòng)處理back按鍵,可通過如下方式關(guān)閉mui的back按鍵監(jiān)聽;

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

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

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

  • 執(zhí)行beforeback參數(shù)對(duì)應(yīng)的函數(shù)若返回false,則不再執(zhí)行mui.back()方法;

  • 否則(返回true或無返回值),繼續(xù)執(zhí)行mui.back()方法;

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

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

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

//備份mui.back,mui.back已將窗口關(guān)閉邏輯封裝的比較完善(預(yù)加載及父子窗口),因此最好復(fù)用mui.backvar old_back = mui.back;mui.back = function(){
  var btn = ["確定","取消"];
  mui.confirm('確認(rèn)關(guān)閉當(dāng)前窗口?','Hello MUI',btn,function(e){
    if(e.index==0){
    	//執(zhí)行mui封裝好的窗口關(guān)閉邏輯;
    	old_back();
    }
  });}
為何設(shè)置了swipeBack: false,在iOS上依然可以右滑關(guān)閉?

iOS平臺(tái)原生支持從屏幕邊緣右滑關(guān)閉,這個(gè)是通過popGesture參數(shù)控制的,參考5+規(guī)范,若需禁用,可通過setStyle方法設(shè)置popGesture為none。

能否通過addEventListener增加back按鍵監(jiān)聽實(shí)現(xiàn)自定義關(guān)閉邏輯?

addEventListener只會(huì)增加新的執(zhí)行邏輯,老的監(jiān)聽邏輯(mui.back)依然會(huì)執(zhí)行,因此,若需實(shí)現(xiàn)自定義關(guān)閉邏輯,一定要重寫mui.back。

預(yù)加載

所謂的預(yù)加載技術(shù)就是在用戶尚未觸發(fā)頁(yè)面跳轉(zhuǎn)時(shí),提前創(chuàng)建目標(biāo)頁(yè)面,這樣當(dāng)用戶跳轉(zhuǎn)時(shí),就可以立即進(jìn)行頁(yè)面切換,節(jié)省創(chuàng)建新頁(yè)面的時(shí)間,提升app使用體驗(yàn)。mui提供兩種方式實(shí)現(xiàn)頁(yè)面預(yù)加載。

方式一:通過mui.init方法中的preloadPages參數(shù)進(jìn)行配置.

mui.init({
  preloadPages:[
    {
      url:prelaod-page-url,
      id:preload-page-id,
      styles:{},//窗口參數(shù)
      extras:{},//自定義擴(kuò)展參數(shù)
      subpages:[{},{}]//預(yù)加載頁(yè)面的子頁(yè)面
    }
  ],
  preloadLimit:5//預(yù)加載窗口數(shù)量限制(一旦超出,先進(jìn)先出)默認(rèn)不限制});

該種方案使用簡(jiǎn)單、可預(yù)加載多個(gè)頁(yè)面,但不會(huì)返回預(yù)加載每個(gè)頁(yè)面的引用,若要獲得對(duì)應(yīng)webview引用,還需要通過plus.webview.getWebviewById方式獲得;另外,因?yàn)閙ui.init是異步執(zhí)行,執(zhí)行完mui.init方法后立即獲得對(duì)應(yīng)webview引用,可能會(huì)失敗,例如如下代碼:

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

方式二:通過mui.preload方法預(yù)加載.

var page = mui.preload({
    url:new-page-url,
    id:new-page-id,//默認(rèn)使用當(dāng)前頁(yè)面的url作為id
    styles:{},//窗口參數(shù)
    extras:{}//自定義擴(kuò)展參數(shù)});

通過mui.preload()方法預(yù)加載,可立即返回對(duì)應(yīng)webview的引用,但一次僅能預(yù)加載一個(gè)頁(yè)面;若需加載多個(gè)webview,則需多次調(diào)用mui.preload()方法;

如上兩種方案,各有優(yōu)劣,需根據(jù)具體業(yè)務(wù)場(chǎng)景靈活選擇;

判斷預(yù)加載是否成功

方式一、通過直觀現(xiàn)象分析

預(yù)加載頁(yè)面會(huì)立即打開,不會(huì)顯示等待框;非預(yù)加載頁(yè)面默認(rèn)會(huì)先顯示等待框,再顯示新頁(yè)面;/p>

方式二、增加log分析預(yù)加載頁(yè)面是否已創(chuàng)建

比如:A頁(yè)面中預(yù)加載B頁(yè)面,則在A頁(yè)面完全加載(可通過setTimeout模擬)后,打印當(dāng)前應(yīng)用所有webview,看是否包含B頁(yè)面的url,以此來分析。

例如:在A頁(yè)面增加如下代碼:

mui.plusReady(function(){
	setTimeout(function(){
		var array = plus.webview.all();
		if(array){
			for(var i=0,len=array.length;i<len;i++){
			    	console.log(array[i].getURL());
		        }
		}
	},5000)}

參考頁(yè)面:http://dev.dcloud.net.cn/mui/window/

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI