html5+iScroll构建WebApp经验总结

来源:互联网 发布:大数据阅读材料答案 编辑:程序博客网 时间:2024/06/14 17:03

html5与iScroll构建WebApp经验总结

1.项目文件结构

首先部署好文件结构,使文件有效整理、归类和引用,快速查找相应文件。

以信息中心应用为例子,以下文件夹结构图:

文件夹结构


  1. app文件夹为存放页面、公共和接口的js文件
  2. jdk文件夹为js库和第三方插件,如iScroll.js/artTemplate.js等等
  3. resources文件夹为存放css文件和图片
  4. 根目录下,存放各页面的html,如index.html。

注意的是easymicore.js和easymilib.js存放根目录,不然无法调用其API。

2.HTML文件基本结构

html5基本结构,如下代码:

<!DOCTYPE html><html>    <head>        <meta charset="UTF-8">        <title>index</title>        <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0, minimum-scale=1.0, maximum-scale=1.0">        <meta name="apple-mobile-web-app-status-bar-style" content="black">        <!-- css文件引用 -->        <link rel="stylesheet" href="resources/css/app.css" />        <!-- js文件引用 -->        <script type="text/javascript" src="easymicore.js"></script>    </head>    <body>        <!-- index视图 -->        <div id="page_index" style = "display:block;">            <div class="header">            </div>            <div id="index_content">            </div>            <div class="footer" id="index_toolbar_footer" style="display:none;">            </div>        </div>        <!-- detail详情视图 -->        <div id="page_detail" style="display:none;">            <div class="header">            </div>            <div id="detail_content">            </div>        </div>        <!-- 遮盖提示视图 -->        <div id = "app_tipMask_id" style = "display:none;">            <div class = "mask">            </div>            <div class="app_tip_inner">            </div>        </div>    </body></html>

主要说明:

meta标签使用
  • <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0, minimum-scale=1.0, maximum-scale=1.0">
    viewport 是移动设备的视图窗口。设置相关值,如下:

    width -        //  viewport 的宽度 (范围从200 到10,000,默认为980 像素),特殊值为device-width 为设备的宽度height -       //  viewport 的高度 (范围从223 到10,000)initial-scale -     //  初始的缩放比例 (范围从0到10)minimum-scale -    //   允许用户缩放到的最小比例maximum-scale -    //   允许用户缩放到的最大比例user-scalable -    //   用户是否可以手动缩 (no,yes),同时可以设置为0,不可缩放
  • 延伸资料:

Mozilla 开发者博客上有 viewport 使用教程。

Apple 开发者站上面有 viewport 详细的描述。

quirksmode.org 有详细的 viewport 在各个手机浏览器不同之处介绍。

  • <meta name="apple-mobile-web-app-status-bar-style" content="black">

设置iOS手机设备上状态条的样式,此设置背景为黑色。

推荐一篇文章《iOS 7 的 Safari 和 HTML5:问题,变化和新 API》

其他meta标签参考

标签规范

为了使页面标签清晰和整洁,如信息应用主要有两个视图,分别为首页定义id="page_index"和详情视图id="page_detail",id值以page开头为全屏视图容器;id以app开头命名则为应用组件,如app_tipMask_id是遮盖提示。

3.单视图布局

通常移动应用布局分为三段式结构,分别是标题栏header、主体内容content、底部工具栏footer(导航栏nar),如下图所示:

toolbar

如何固定标题栏和工具栏?
运用了position:absoulte进行绝对定位,代码如下:

.header,.footer {    width:100%;    height:45px;    line-height:45px;    color: white ;    padding:0;    font-size:22px;    text-align:center;    background-color: #5A5AEC;}.header {    position:absolute;    top:0; left:0;}.content {    margin-top: 47px;    width: 100%;    height: 100%;}.footer {    position:absolute;    bottom:0; left:0;}

position:fixed;同样可以固定位置,但fixed在一些移动设备浏览器不支持(具体无测试)。

还有一个问题如何使content区域滚动,content的height:100%,其内容变化而高度大于设备高度屏幕时候,则显示原生滚动条,导致可以滚动整个页面。

而选择position:absoulte搭配iScroll组件实现固定区域滚动,这样可以解决区域滚动的问题。

使用iScroll比较简单,编写一个合理DOM结构:

<div id="content">    <ul id="scroll">        <li></li>        ...    </ul></div>

content样式:

#content {    position:absolute; z-index:1;    top:45px; bottom:0px; left:-9999px;    width:100%;    overflow:auto;}

其中left:-9999px;,初始化的时候设置left:0px;。其效果是缓冲过程,不会很突兀立即显示滚动区域的内容。

官方推荐这样的结构,因为iscroll只能滚动wrapper里的第一个子节点,或者说唯一一个子节点才能使得iscroll正确的生效。因为这个节点需要一个绝对定位的CSS属性,更重要的是这个节点里所包裹的内容有了一个统一的容器,我们只需要计算之后修改这个容器的属性值就可以达到我们滚动的效果。

iscroll 需要两个参数,第一个很简单就是外容器的id,第二个参数是一个参数对象。

<script>    var myscroll=new iScroll("content",{hScrollbar:false, vScrollbar:false});</script>

通过这个对象可以传入iscroll的各项参数来配置iscroll。
常用参数基本分为四个部分

  • 基础
  • 滚动条
  • 放大缩小
  • 事件回调
基本参数
hScroll: true, //是否水平滚动vScroll: true, //是否垂直滚动x: 0, //滚动水平初始位置y: 0, //滚动垂直初始位置bounce: true, //是否超过实际位置反弹bounceLock: false, //当内容少于滚动是否可以反弹momentum: true, //动量效果,拖动惯性lockDirection: true,//当水平滚动和垂直滚动同时生效时,当拖动开始是否锁定另一边的拖动useTransform: true, //是否使用CSS形变useTransition: false, //是否使用CSS变换topOffset: 0, //已经滚动的基准值checkDOMChanges: false, //是否自动检测内容变化
滚动条
hScrollbar: true, //是否显示水平滚动条vScrollbar: true, //同上垂直滚动条fixedScrollbar: isAndroid, //在iOS系统上,当元素拖动超出了scroller的边界时,滚动条会收缩,设置为true可以禁止滚动条超出scroller的可见区域。hideScrollbar: isIDevice, //是否隐藏滚动条fadeScrollbar: isIDevice && has3d, //滚动条是否渐隐渐显scrollbarClass: '', //字定义滚动条的样式名

通过scrollbar这些参数可以配置iscroll的滚动条,通过scrollbarClass可以自己定义一套滚动条的样式。

放大缩小
zoom: false, //默认是否放大zoomMin: 1, //放大的最小倍数zoomMax: 4, //最大倍数doubleTapZoom: 2, //双触放大几倍wheelAction: 'scroll', //鼠标滚动行为;none不支持,scroll鼠标滚动,zoom鼠标缩放

在低端移动设备测试,放大缩小不是很好支持。

事件回调
onRefresh: null, //refresh 的回调onBeforeScrollStart: function (e) { e.preventDefault(); },//开始滚动前的时间回调,默认是阻止浏览器默认行为onScrollStart: null, //开始滚动的回调onBeforeScrollMove: null, //在内容移动前的回调onScrollMove: null, //内容移动的回调onBeforeScrollEnd: null, 在滚动结束前的回调onScrollEnd: null, //在滚动完成后的回调onTouchEnd: null, //手离开屏幕后的回调onDestroy: null, //销毁实例的回调onZoomStart: null,//放大开始时的回调onZoom: null,//放大时的回调onZoomEnd: null//放大结束时的回调

监听滚动下拉和下拉,会常用到onRefresh、onScrollMove、onScrollEnd的事件实现下拉刷新和上拉翻页逻辑功能。

其中下拉刷新实现原理

  • 通过 topOffset 参数属性设置iScroll已经滚动的基准值;
  • 通过 onScrollMove 参数方法判断当前滚动是到顶端还是底端;
  • 通过 onScrollEnd 参数方法触发加载新数据,再通过 refresh 方法重新渲染界面;
  • 通过 onRefresh 参数方法调整刷新后的界面结构;

简单代码如下:

var myScroll =new iScroll("content",{    topOffset: 50,    onRefresh: function(){},    onScrollMove: function(){},    onScrollEnd: function(){}});

官方有一个下拉和上拉例子,修改其代码成为自己组件。

scroll

iScroll常用方法API

refresh
这个方法非常有用,当你的滚动区域的内容发生改变 或是 滚动区域不正确,都用通过调用refresh 来使得iscroll 重新计算滚动的区域,包括滚动条,来使得iscroll 适合当前的dom。

scrollTo
这个方法接受4个参数 x, y, time, relative x 为移动的x轴坐标,y为移动的y轴坐标, time为移动时间,relative表示是否相对当前位置。可以实现自动刷新方法。

参考更多资料:

  • iScroll4中文API

  • iScroll4官方

  • iScroll5官方 其中iScroll5暂时没有支持拉动刷新,因为删除了topOffset属性

iScroll使用遇到问题
  • 当滚动区域内容为空时,无法触动滚动条。

解决办法:当请求数据为空且当前列表没有元素时候,滚动标签添加手机设备高度的div标签(没有任何属性)来充当可滚动内容。

  • 当滚动区域内容比较少的时候,会同时触发下拉和上拉事件。

解决办法:检测列表小于请求更新条数时,禁止上拉事件触发,隐藏上拉提示区域。

4.视图切换

根据标签规范,理顺各个页面标签划分。对于视图切换就很容易,主要用元素属性style.display设置,显示为block,隐藏则为none进行视图切换。display设置隐藏则不占页面空间,如果想标签元素占页面空间,可以用style.visibility="visible|hidden"进行设置。但是注意页面切换最好使用display进行显示和隐藏,若使用visibility,一个页面显示时,其他页面隐藏也占空间,显示一段空白区域。

如果想增强视图切换效果,如滑入滑出、谈入谈出等等效果,用CSS3动画属性transitiontransform制作动画效果。

视图切换谈入谈出,其原理是切面切换时,设置标签元素为遮盖模式显示,遮盖背景为白色,用transition在400ms变换把透明度1为0,最后此标签隐藏。代码如下:

/*淡入淡出*/.mask {    z-index: 199;    display: block;    width:100%;    height:100%;    visibility: hidden;    opacity: 0;    position: absolute;    top:0px;    left:0px;    background-color:white;}.mask.show {    visibility: visible;    -webkit-transition: opacity 400ms;    opacity: 1;}.mask.hide {    visibility: visible;    -webkit-transition: opacity 400ms;    opacity: 0;}

滑入滑出效果,其中运用CSS3中translate3d转换属性,代码如下:

.next {    display: block;    -webkit-transform: translate3d(100%,0,0);}.next.in{    -webkit-transition: -webkit-transform 600ms;    -webkit-transform: translate3d(0,0,0);}.currentpage.out {    -webkit-transition: -webkit-transform 600ms;    -webkit-transform: translate3d(-100%,0,0);}.currentpage.back {    -webkit-transition: -webkit-transform 600ms;    -webkit-transform: translate3d(100%,0,0);}.currentpage {    z-index:100;    display:block;}

考虑在低端手机上CSS3显示效果欠佳,特别是translate3d属性,增加GPU渲染,导致其执行代码效率低,在实际项目中没有使用CSS3动画效果。推荐使用谈入谈出效果。

5.视图之间数据传送问题

以信息中心应用总共只有两个视图,页面结构比较简单,所以两个视图都写在index.html中,这样视图之间数据传送也比较简单,把临时共享数据定义数据接口空间域名dao对象中。

假如视图复杂且多的时候,各个视图设置单独html进行管理,而视图之间数据传送,则依靠sessionStorage为传播中介。sessionStorage和localStorage存储方式一样,不同的是关闭应用或浏览器后,sessionStorage不会保存里面的值。

用视图切面以及sessionStorage保存临时数据例子:

6.在android移动设备上一些问题

在android移动设备上,点击列表时候,触发两次点击事件。

原因是iscroll在判断滑动前,阻止了click事件,然后在滑动后,对原来的click事件进行了重构,一些设备上,特别是android移动设备,并没有将默认的click阻止掉。

问题解决是利用两次点击时间差内(大概320ms),阻止第二次点击事件触发。

var toogleSelectTag = false;function selectItem(e,itemId){    if(toogleSelectTag){        e.preventDefault();        e.stopPropagation();        return;    }    toogleSelectTag = true;    setTimeout(function () {        toogleSelectTag = false;    },320);    //do to something}

7.穿透现象

遮盖层上分组列表点击时,会把分组列表和遮盖层隐藏,同时触发信息列表点击事件,跳转到详情视图。

原因是同样iscroll问题,触发两次点击事件。

问题解决:点击分组列表时,不阻止事件冒泡e.stopPropagation();,让同时触发遮盖点击事件。

8.artTemplate模板引擎

artTemplate官网,查看官网使用例子。

信息中心应用使用简洁版,大小只有5k,比mustache模板引擎少了1k。使用过程注意的是,实际例子中数据存在html标签,所以我们模板默认会把html标签进行转义,如<p>标签</p>转义标签,把<p>标签删掉。不需要转义,只需要数据前加#号,如{{#"<p>标签</p>"}}

9.移动设备点击优化

在移动设备上,由于两次连续“轻触”是“放大”的操作(即使你两次轻触的是一个链接或一个有click事件监听器的元素),所以在第一次被“轻触”后,设备需要先等一段时间,看看有没有所谓的“连续的第二次轻触”。如果有,则进行“放大”操作。没有,才敢放心地认为用户不是要放大,而是需要“click”至此才敢触发click事件,导致“短按(手指接触屏幕到离开屏幕的时间比较短)”的click事件通常约会延迟300ms左右,同样快速点击或长按时候,没有触发点击事件。而用touchstarts事件,则手指触摸开始即能触发,不能简单代替clilk事件。

使用fastclick插件模拟点击事件,规避click在移动手持设备上带来的延迟。

在上图中,方框A简单click事件,而FastClick方法封装方框B的点击事件。明显在浏览器中方框B没有延时,代码如下:

var testA, testB, teTime, cTime;testA = document.getElementById('test-a');testB = document.getElementById('test-b');FastClick.attach(testB);testA.addEventListener('touchend', function(event) {    teTime = Date.now();    document.getElementById('te-time').value = teTime;}, false);testA.addEventListener('click', function(event) {    cTime = Date.now();    document.getElementById('c-time').value = cTime;    document.getElementById('d-time').value = cTime - teTime;    testA.style.backgroundColor = testA.style.backgroundColor ? '' : 'YellowGreen';}, false);testB.addEventListener('touchend', function(event) {    teTime = Date.now();    document.getElementById('te-time').value = teTime;    document.getElementById('d-time').value = cTime - teTime;}, false);testB.addEventListener('click', function(event) {    cTime = Date.now();    document.getElementById('c-time').value = cTime;    testB.style.backgroundColor = testB.style.backgroundColor ? '' : 'YellowGreen';}, false);

参考资料:
factclick官网

10.android上点击时出现的橙色框的设置为透明

-webkit-tap-highlight-color:rgba(255,255,255,0);
0 0
原创粉丝点击