0%

Mui-note

1. MUI定位:最接近原生体验的移动App的UI框架

基于mui的定位。产生了mui的几个特点,轻、小、只涉及UI、只为移动App而生、界面风格原生化。

1.1 mui不是jq,不封装dom操作

与ui无关的mui不做,你愿意用jq或zepto就自己用,并不冲突。但我们并不建议在移动App里引入jq或zepto这些框架,原因如下:为了性能,层层封装的框架,尤其是遍历循环dom时,影响效率,尤其在地段Android手机上,我们费死劲才能把性能以毫秒为单位一点点提升,搞这个dom框架进来就让很多努力付诸东流

1.2 原生js挺简单,为何需要jq?

jq的成功当时时因为ie6、7、8、9、10、chrome、ff这些浏览器不兼容,让开发者崩溃,而且pc上浏览器性能号,跨平台兼容也不影响性能。但jq根本不是为手机设计的。手机上只有webkit浏览器(忽略wp,反正mui不支持wp),根本就不需要jq这种封装框架来操作dom。而HBuilder提供了代码块来简化开发,敲dg、dq,直接生成document.getElementById(“”)、document.querySelectorAll(“”),非常快捷方便,而且执行性能非常高,并且没有浏览器兼容性问题。

1.3 mui、HTML5+、5+Runtime的关系说明

mui是一个前端框架,HTML5+是一套HTML5能力扩展规范,HTML5+Runtime是实现HTML5+规范的强化浏览器引擎。有点类似于bootstrap、五c和chrome os关系。

HTML5+规范隶属于http://www.html5plus.org,定义了HTML5规范中没有但开发者做APP需要的扩展规范

DCloud的5+Runtime完整的实现了HTML5+规范。同时5+Runtime还实现了Native.js。一种通过js调用几十万原生API技术。为了提升体验,mui势必会调用一些5+Rutime的增强能力,主要是plus.webview和plus.nativeUI.但mui不是要替代HTML5Plus,以后也无法替代把所有5+的webview api都包一层

2. 创建应用

2.1 Hbuilderx 下载

https://www.dcloud.io/hbuilderx.html

2.2 创建项目

2.3 目录结构

  • css 样式表文件夹
  • fonts 字体文件夹
  • js JavaScript脚本文件
  • index.html 入口文件(首页)
  • mainfiest.json 项目配置文件 具体参考https://ask.dcloud.net.cn/article/94

2.4 基础布局

  • 头部

    核心css mui-bar mui-bar-nav

    标题

  • 主体部分

    主体部分

2.5 UI组件文档

https://dev.dcloud.net.cn/mui/ui/

2.6 MUI-窗口管理及窗口直接点数据传递

  1. mui插件初始化

    使用mui.init();进行mui插件初始化

  2. 页面初始化

    在app开发中,若要是哟个HTML+5扩展api,必须等plusready事件执行后才能正常使用,mui将该事件封装成了mui.plusReady()方法,涉及到HTML5+的api,建议都卸载mui.plusReady方法中。如下为打印当前页面URL实例

    1
    2
    3
    mui.plusReady(function(e){
    console.log("当前页面的URL:"+plus.webview.currentWebview().getURL())
    })
  3. 创建子页面

    在移动app开发过程中,经常遇到卡头卡尾的页面,此时若使用局部滚动,在andorid手机上会出现滚动不流畅的问题;mui的解决思路是:将需要滚动的区域通过单独的webview实现,完全使用原生滚动。具体做法:

    将目标页面分解为主页面和内容页面,主页面显示卡头卡尾区域,比如顶部导航栏、底部选项卡等;内容页面显示具体需要滚动的内容,然后在主页面中调用mui.init()方法初始化内容页面

  4. 做web app,一个无法避开的问题就转场动画;web是基于链接构建的,从一个页面点击跳转到另一个页面,如果通过有刷新的的打开方式,用户要面对一个空白的页面等待;如果通过无刷新的方式,用JavaScript移入DOM节点(常见的SPA解决方案),会碰到很高性能的挑战,DOM节点繁多,页面太大,转场动画不流畅甚至导致浏览器崩溃;mui的解决思路是:单webview只承载单个页面dom,减少dom的嵌套层级及页面大小;页面切换使用原生动画,将最耗性能的部分交给原生实现

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    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,//等待框背景区域高度,默认根据内容自动计算合适高度
    ......
    }
    }
    })

    子页面接收参数核心代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    <script type="text/javascript">
    const vm = new Vue({
    el: '#app',
    data: {
    arr: new Array(20),
    mData: {
    },
    },
    methods: {
    initData() {
    const _this = this;
    console.log(_this)
    mui.init()
    // 非真机情况下,此函数是不生效的
    mui.plusReady(function() {
    const sData = plus.webview.currentWebview();
    _this.mData = sData;
    console.log(_this.mData.name)
    })
    }
    },
    mounted() {
    this.initData();

    }
    })
    </script>
  5. 预加载

    所谓的预加载技术就是在用户尚未触发页面跳转时,提前创建目标页面,这样当用户跳转时,就可以立即进行页面切换,节省创建新页面的时间,提升app使用体验。mui提供两种方式实现页面预加载。

    方式一:通过mui.init方法中的preloadPages参数进行配置.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    mui.init({
    preloadPages:[
    {
    url:prelaod-page-url,
    id:preload-page-id,
    styles:{},//窗口参数
    extras:{},//自定义扩展参数
    subpages:[{},{}]//预加载页面的子页面
    }
    ],
    preloadLimit:5//预加载窗口数量限制(一旦超出,先进先出)默认不限制
    });

    该种方案使用简单、可预加载多个页面,但不会返回预加载每个页面的引用,若要获得对应webview引用,还需要通过plus.webview.getWebviewById方式获得;另外,因为mui.init是异步执行,执行完mui.init方法后立即获得对应webview引用,可能会失败,例如如下代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    mui.init({
    preloadPages:[
    {
    url:'list.html',
    id:'list'
    }
    ]
    });
    var list = plus.webview.getWebviewByid('list');//这里可能返回空;

    方式二:通过mui.preload方法预加载.

    1
    2
    3
    4
    5
    6
    var page = mui.preload({
    url:new-page-url,
    id:new-page-id,//默认使用当前页面的url作为id
    styles:{},//窗口参数
    extras:{}//自定义扩展参数
    });

    通过mui.preload()方法预加载,可立即返回对应webview的引用,但一次仅能预加载一个页面;若需加载多个webview,则需多次调用mui.preload()方法;

    如上两种方案,各有优劣,需根据具体业务场景灵活选择;

3 事件绑定

可以使用addEventListener()方法监听某个元素上的事件外,也可使用.on方法实现批量元素的事件绑定。addEventListener(单个元素事件绑定)

1
2
3
4
5
6
7
// 非真机情况下,此函数是不生效的
mui.plusReady((e) => {
document.getElementById('btn1').addEventListener('tap', function() {
mui.alert("被点击")
})

})

on()示例,适用于批量元素的绑定:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
mui.init({
gestureConfig: {
longtap: true, //默认为false
}

})

// 非真机情况下,此函数是不生效的
mui.plusReady((e) => {
document.getElementById('btn1').addEventListener('longtap', function() {
mui.alert("被点击")
})

mui('#list').on('tap', 'li', function() {
const obj = JSON.stringify(e)
console.log(this.innerHTML)
mui.toast(this.innerHTML)
console.log("执行完毕")

})
// 取消事件
mui('#list').off('tap','li')
})

4 模拟触发事件

使用mui.trigger()方法可以动态触发特定DOM元素上的事件

1
2


5 手势事件

6 自定义事件

在App开发中,经常会遇到页面间传值的需求,比如从新闻列表页进入详情页,需要将新闻id传递过去; Html5Plus规范设计了evalJS方法来解决该问题; 但evalJS方法仅接收字符串参数,涉及多个参数时,需要开发人员手动拼字符串; 为简化开发,mui框架在evalJS方法的基础上,封装了自定义事件,通过自定义事件,用户可以轻松实现多webview间数据传递。

仅能在5+ App及流应用中使用

因为是多webview之间传值,故无法在手机浏览器、微信中使用;

监听自定义事件

添加自定义事件监听操作和标准js事件监听类似,可直接通过window对象添加,如下:

1
2
3
4
window.addEventListener('customEvent',function(event){
//通过event.detail可获得传递过来的参数内容
....
});

触发自定义事件

通过mui.fire()方法可触发目标窗口的自定义事件:

7 官方文档

谢谢老板