移动 Web 单页应用开发实践——页面结构化
在开发面向现代智能手机的移动Web应用的时候,无法避免一个事实,就是需要开发单页应用(Single Page WebApp)。对于不同的系统需求,单页应用的粒度会不同,可能是整个系统都使用一个页面装载,也可能是按模块分为独立页面装载。在开发单页应用时第一个要处理的问题就是页面结构化,由于多个功能集中在一个页面呈现,就必然需要考虑如何实现多个视图布局?如何实现视图之间动画切换?等问题。
下面我就来讲述下手机搜狐 前端团队在单页应用开发的页面结构化上做过的一些尝试与努力。
2. 页面视图
在讲页面结构化之前需要先理解视图的概念,视图是单页应用开发中最常见的模块,通常在一个单页应用中,会有多个视图存在,每一个视图都可以处理一部分业务功能,所有视图的功能集就是单页应用所能处理业务的最大能力。下面介绍几种单页应用中最常出现的几种视图。
2.1 单视图层
三段式结构是单视图的一种最基本布局方式,如下图:
单视图并不一定都有head或foot,所以Header、Footer使用虚线来表示。多数应用中还会有导航条(Navigatior),但一般情况下导航条会被计算为Header或Content的一部分,而不会独立存在。
2.2 侧边栏
侧边栏是一种特殊的视图,在不显示时,当前视图是盖在侧边栏至上的,当它被呼出时,视图一部分滑出屏幕外,侧边栏才被显示出来,它的高度等于页面可视区域的高度。
2.3 封面图
封面图与侧边栏类似,也是一个特殊的视图。封面图一般会在页面初始时候出现,而后消失,消失之后就不再出现。它的视图层级是最高的,并且完全覆盖于其他页面元素,它的高度会大于或等于可视区域的高度。
3 多视图布局
单页应用中第一个要思考的问题就是:如何实现多视图的布局?通常我们会将视图的定位设置为position:absolute,这是一种简单又实用的方法。在一个时间节点上,页面可视区域只能有一个可见的当前视图,虚线表示其他视图,在页面可视区域之外不可见(display:none),如下图:
使用伪代码表示:
<style type="text/css">
.view {
position: absolute;
top: 0;
left: 0;
z-index: 99;
display: none;
width: 100%;
height: 100%;
}
.current {
z-index: 100;
display: block;
}
</style>
<div class="view current"></div>
<div class="view"></div>
此时,我们需要思考另一个问题:如何实现当前视图的 Content 区域内容滚动?视图的样式高度设置为height:100%,将视图高度设定为一屏高的目的是为了方便实现视图动画切换的效果(视图动画切换会在后面详细的讲)。但这样做会导致另一个问题,高度为一屏高意味着浏览器滚动条失效,无法使用浏览器滚动条滚动页面。
3.1 基于 iScroll 的多视图布局
现在比较流行的一种解决方案是使用iScroll 组件实现固定区域滚动,这样就能解决Content区域的滚动问题,在手机搜狐的早期项目也是这么做的。此外,使用iScroll还额外带来了一些好处,如:
- Header区域能固定在页面顶部,不会因为Content区域滚动导致Header被顶上去;
- 单视图的高度控制在一屏高,这样有利于实现视图之间的动画切换;
对于这种结构的应用,在使用视图切换的时候就非常好做,使用CSS3的transition来完成动画切换,如下图:
使用伪代码表示:
<style type="text/css">
.current.out { -webkit-transition: -webkit-transform 400ms; -webkit-transform: translate3d(-100%,0,0); }
.next { display: block;
-webkit-transform: translate3d(100%,0,0); }
.next.in{ -webkit-transition:
-webkit-transform 400ms; -webkit-transform: translate3d(0,0,0);
}
</style>
<div class="view current out"></div>
<div class="view next in"></div>
视图切换的动画效果可以根据业务需求定制,比如:由左向右滑动、由右向左、由上到下、右下到上等都是可以的。在完成切换动画时,再将next视图的状态设置为current,如下:
<div class="view"></div>
<div class="view current"></div>
下图是项目中使用的一个由下往上动画切换效果:
3.2 iScroll页面结构下的侧边栏
使用iScroll的页面结构,无论是侧边栏还是封面图都非常好实现,看伪代码:
侧边栏,默认状态
<style type="text/css"> .sidebar { z-index: 50; display: block; width: 80%; } .sidebar.show + .current { -webkit-transition: -webkit-transform 400ms; -webkit-transform: translate3d(80%,0,0); } .sidebar.hide + .current { -webkit-transition: -webkit-transform 400ms; -webkit-transform: translate3d(0,0,0); }</style><div class="view sidebar"></div><div class="view current"></div>
侧边栏显示时
<div class="view sidebar show"></div><div class="view current"></div>
侧边栏隐藏时,当hide动画结束之后,移除hide样式
<div class="view sidebar hide"></div><div class="view current"></div>
3.3 iScroll页面结构下的封面图
封面图的实现与侧边栏差不多。
封面图,默认状态
<style type="text/css"> .cover { z-index: 200; display: block; visibility: hidden; opacity: 0; } .cover.show { visibility: visible; -webkit-transition: opacity 400ms; opacity: 1; } .cover.hide { visibility: visible; -webkit-transition: opacity 400ms; opacity: 0; }</style><div class="view cover"></div><div class="view current"></div>
封面图显示时
<div class="view cover show"></div><div class="view current"></div>
封面图隐藏时,当hide动画结束之后,移除hide样式
<div class="view cover hide"></div><div class="view current"></div>
在项目中的实现效果:
3.4 iScroll对内容刷新的支持
对于Content区域的内容刷新iScroll也有很好的支持,可以直接参见iScroll提供的例子:http://lab.cubiq.org/iscroll/examples/pull-to-refresh/
**Note:**iScroll目前已经更新到了5.0的版本,大家可以关注Github项目https://github.com/cubiq/iscroll/


