文章来源:小青年原创
发布时间:2016-07-26
关键词:mui,webview,template,os,多端适配
转载需标注本文原始地址: http://zhaomenghuan.github.io...css
自历来公司实习,天天都淹没在问题中,一直没有抽出空写写文章,今天轮到我完善文档和总结,就想着抽空把文档中的内容写写,可是文档限于篇幅,并且不能话唠,天然博客是最好的方式去分享。哈哈,废话很少说,将整理的内容贴出来,稍做解释,方便你们查阅。html
hello mui示例App中无等待窗体切换的实现是基于模板页面,点击一个连接,不显示雪花等待框,当即打开一个“正在加载...”的页面,以后真实内容快速填充“正在加载...”区域。这种模板页面适用了通用性较强的页面,咱们没必要要为每一个页面建立父子webview,而是将公用的父页面提取出来做为模板页面,同时在页面为加载前能够显示个性化加载页面,能够极大的提高用户体验。模板父页面预加载,点击后当即显示,不用展现雪花等待框,也不会出现白屏现象;共用子页面,有效控制webview数量,避免切页时频繁建立、销毁webview。html5
这里咱们以列表到详情页的状况为例说明,详情页html结构:android
<ul class="mui-table-view"> <li class="mui-table-view-cell"> <a class="mui-navigate-right" href="list1.html"> Item 1 </a> </li> <li class="mui-table-view-cell"> <a class="mui-navigate-right" href="list2.html"> Item 2 </a> </li> <li class="mui-table-view-cell"> <a class="mui-navigate-right" href="list3.html"> Item 3 </a> </li> </ul>
1.预加载一个模板父页面,用以当页面尚未加载出来的时候展现加载动画,以及做为公用子页面的头部,原理至关于tabbar webview模式的父页面;预加载或者建立一个公用子页面,同时将这个子页面填充到模板父页面;ios
// 预加载模板父页面 var template = mui.preload({ url:'template.html', id:'template', styles:{ popGesture:"hide" } }); // 预加载公用子页面 var subWebview = mui.preload({ url:'', id:'sub_template', styles:{ top: '45px', bottom: '0px' } }); // 将子页面填充到父页面 template.append(subWebview);
2.点击列表连接时,直接显示模板父页面,并动态修改模板父页面的标题;共用子页面经过loadURL方法加载对应目标页面;git
mui('.mui-table-view').on('tap','li a',function(){ var self = this; // 修改共用父模板的标题 mui.fire(template, 'updateHeader', { title: self.innerText, href: self.href }); // 加载子页面地址 if(subWebview.getURL()==self.href){ subWebview.show(); }else{ subWebview.loadURL(self.href); // 子页面加载完成显示 subWebview.addEventListener('loaded', function() { setTimeout(function(){ subWebview.show(); },50); }); } // 显示模板父页面 template.show('slide-in-right', 150); })
3.模板父页面接收参数和返回列表页的处理方法github
var titleElem = document.getElementById("title"); var contentWebview = null,self = null; mui.plusReady(function () { self = plus.webview.currentWebview(); }); // 自定义事件接收参数修改模板父页面头部 window.addEventListener("updateHeader", function(e) { var title = e.detail.title; var href = e.detail.target; var aniShow = e.detail.aniShow; titleElem.innerHTML = title; titleElem.className = "mui-title mui-fadein"; if(mui.os.android&&aniShow&&parseFloat(mui.os.version)>=4.4){ if(contentWebview==null){ contentWebview = self.children()[0]; } if (contentWebview.getURL() != href) { contentWebview.loadURL(href); } else { contentWebview.show(); } setTimeout(function () { self.show(aniShow); },10); } }); // 返回事件(隐藏模板父页面,并在窗体动画结束后,隐藏共用子页面) mui.back = function() { self.hide('auto'); setTimeout(function() { titleElem.className = 'mui-title mui-fadeout'; titleElem.innerText = ''; if(contentWebview==null){ contentWebview = self.children()[0]; } contentWebview.hide("none"); }, 350); }
另外须要说明的是,咱们这种方式是建立两个webview做为视图容器实现,在web环境下webview的方法不能执行,hello mui里面为每一个详情页面建立一个头部,可是咱们会发如今app环境下执行并无出现这个头部,这是觉得在hello mui演示demo中的app.css中有这么一段代码:web
.mui-plus.mui-android header.mui-bar{ display: none; } .mui-plus.mui-android .mui-bar-nav~.mui-content{ padding: 0; }
因为iOS系统性能已经足够好,转场切换不会白屏,hello mui演示demo中iOS没有使用模板页面。当咱们引入mui.js文件,在5+环境执行,mui.js会自动将.mui-plus
及.mui-plus-android
类添加到body上,咱们能够经过这个方法进行环境判断,是否显示某些内容。segmentfault
若是是写文档,写到上面天然就戛然而止,可是写文章,但愿把这个相关的问题顺便多聊几句,由于一旦有人遇到相关的问题,多说了几句就说不定解决的。浏览器
说到系统判断,这里不得不说一下mui.os这个工具方法,mui经过封装html5中的navigator.userAgent
API进行判断系统和版本号:
5+环境下判断方法:
mui.os.plus 返回是否在5+基座中运行
等效于:navigator.userAgent.indexOf("Html5Plus")>-1
mui.os.stream 返回是否为流应用
等效于:navigator.userAgent.indexOf("StreamApp")>-1
Android环境下判断方法:
mui.os.android 返回是否为安卓手机
等效于:navigator.userAgent.indexOf("Android")>-1
mui.os.isBadAndroid android非Chrome环境
等效于:!(/Chrome\/\d/.test(window.navigator.appVersion))
mui.os.version 安卓版本
等效于:navigator.userAgent.match(/(Android);?[\s\/]+([\d.]+)?/)[2]
IOS环境下判断方法:
mui.os.ios 返回是否为苹果设备
等效于:navigator.userAgent.indexOf("iPhone")>-1&&navigator.userAgent.indexOf("iPad")>-1
mui.os.iphone 返回是否为苹果手机
等效于:navigator.userAgent.indexOf("iPhone")>-1
mui.os.ipad 返回是否为ipad
等效于:navigator.userAgent.indexOf("iPad")>-1
mui.os.version 返回手机版本号
等效于:navigator.userAgent.match(/(iPhone\sOS)\s([\d_]+)/).[2].replace(/_/g, '.')||navigator.userAgent.match(/(iPad\sOS)\s([\d_]+)/).[2].replace(/_/g, '.')
微信环境下判断方法:
mui.os.wechat 返回是否为微信端
等效于:navigator.userAgent.indexOf("MicroMessenger")>-1
mui.os.wechat.version 返回微信版本
等效于:navigator.userAgent.match(/(MicroMessenger)\/([\d\.]+)/i)[2].replace(/_/g, '.')
这里咱们能够经过mui.os.*
方法进行判断,可是不少时候咱们须要更简单的方法去判断,好比咱们但愿某一部份内容只在5+环境下显示,有些内容只在非5+环境下执行,或者有些内容只在微信环境下使用,使用mui.os.*
有时候显得仍是不够方便,那这里就说一个更简单的方法,就是咱们上面讲到的经过设置class类的CSS方法。
读mui源码咱们可以知道,mui中定义mui.os.*
系列方法,同时经过mui.os.*
方法判断环境,将.mui-plus
,.mui-plus-stream
,.mui-ios
,.mui-android
,.mui-wechat
,mui-ios-version
,mui-android-version
,mui-wechat-version
绑定在document.body.classList
中,咱们能够经过这些样式类判断当前的运行判断,因而能够作出一些适配。
.mui-plus-visible, .mui-wechat-visible{ display: none!important; } .mui-plus-hidden, .mui-wechat-hidden{ display: block!important; } .mui-plus .mui-plus-visible, .mui-wechat .mui-wechat-visible{ display: block!important; } .mui-plus .mui-tab-item.mui-plus-visible, .mui-wechat .mui-tab-item.mui-wechat-visible{ display: table-cell!important; } .mui-plus .mui-plus-hidden, .mui-wechat .mui-wechat-hidden{ display: none!important; }
当咱们知道这些类的时候,在作适配的时候能够解决不少小问题,以下面这个例子:
<div class="mui-input-row mui-plus-visible"> <label>mui-plus-visible</label> <input type="text" class="mui-input-speech mui-input-clear" placeholder="我在web环境下隐藏5+环境下显示"> </div> <div class="mui-input-row mui-plus-hidden"> <label>mui-plus-hidden</label> <input type="text" class="mui-input-clear" placeholder="我在web环境下显示5+环境下隐藏"> </div>
咱们可使用.mui-plus-visible
将只能在5+环境下正常使用的内容在web环境下隐藏,反过来咱们可使用 .mui-plus-hidden
将在web中正常显示的内容在5+环境下隐藏。在5+环境下咱们使用加强版的语音输入,在普通web环境下使用h5的普通输入框。
开发一次,多端发布,我想这种不少人但愿看到的,目前mui中不少组件已经实如今多平台自动切换到合适的模式,使用最合适的姿式,可是对于业务要求各不相同的开发者,想要实现多端发布,不是简单的一两句的问题,仍是得熟悉各个平台的差别化,同时对于h5,mui,html5+中的实现方法的差别要全部了解的前提下,才可以作到真正的多端发布。
上面讲解了多端发布的时候系统及版本判断的方法,可是依然没有说明区别所在,估计不少人看了依然是懵逼状态。为解决HTML5在低端Android机上的性能缺陷,mui引入了原生加速,在普通浏览器端5+的一些方法再也不适用,因此作多端发布的时候必须先明白哪一些方法可使用,哪一些不能使用。所以若是不是APP端,须要将5+的方法所有替换成h5的方法。
mui中最关键的5+模块是webview控件,所以mui若要发挥其所有能力,凡是涉及到webview窗体的内容在非5+环境不能使用,涉及功能点包括:
webview模式窗体动画
建立子窗口(除了为解决区域滚动的常见双webview场景,还涉及webview模式的选项卡等多webview场景)
webview模式的侧滑菜单(也有div方式侧滑菜单)
webview模式的tab选项卡(也有div方式选项卡)
nativeUI,如原生的警告框、确认框、popover、actionsheet、toast。这些也有HTML5的实现。
预加载
页面传值(拓展参数及自定义事件)
对于这部分的内容,解决方法也有不少,若是mui提供了iframe模式的父子页面(主要兼容上拉加载下拉刷新),div模式的、侧滑菜单、选项卡、弹出框,页面传值也可使用url传参或localStorage等本地存储的方法。在mui初级入门教程(二)— html5+ webview 底部栏用法详解一文中我也给出了iframe兼容webview模式tabbar的解决方法。
对于第三方插件,html5+中的方法能够优雅降级处理,采用h5的相关标准去实现,好比dcloud官方给出了一个定位的例子,查看这里plusto,plusto是为实现多端发布的一个开源JS库,该库能够根据平台实现API的自动转换,好比在5+ App环境下,将浏览器默认定位升级为5+原生定位,实现一套代码平滑迁移至多个平台。在微信中有jssdk一样能够调用系统的一些功能,你们能够自行判断。
或许有些人喜欢使用一些构建工具,对于多端发布使用构建工具确实会很方便,可是对于小白用户来讲,可能会遇到更多问题,DCloud的mui及Hello mui示例是使用grunt构建的,grunt相关配置也都开源,感兴趣的朋友能够自行构建,后面有时间再整理一篇相关的文章加以说明。
hello mui中的无等待窗体切换是如何实现的
mui适用场景说明,能不能在普通浏览器里使用,可否用于wap网站
多端发布开发指南
这篇文章基本都是copy相关的文档,加以增删,乃成此文。很久不写文,大神勿喷!
最后放上demo地址:
mui-demo:https://github.com/zhaomenghu...
写文章不容易,也许写这些代码就几分钟的事,写一篇你们好接受的文章或许须要几天的酝酿,而后加上几天的码字,累并快乐着。若是文章对您有帮助请我喝杯咖啡吧!
近期在segmentfault讲堂开设了一场关于html5+ App开发工程化实践之路的讲座,会讲到5+ 开发中高性能的优化方案以及使用如何结合Vue.js进行开发,欢迎前来围观:https://segmentfault.com/l/15...。