黄丽琼, 李墨墨, 齐文豪
(商洛学院 数学与计算机应用学院, 商洛 726000)
国际上,从2009年的Angular到2013年的React,再到2014年的Vue,各大以MVC为架构模式,SPA(single page web application 单页面应用)为应用核心的单页面应用框架应运而生[1-2]。本文通过html,less结合外卖平台作为蓝本搭建了单页面应用的功能表现载体——应用主页面,使用JavaScript的面向对象编程思想编写了弹窗组件,利用Angular构建了MVC的架构模式,让应用实现视图、模型、逻辑的分层,使用Angular命名空间、依赖注入以及JavaScript的闭包实现了应用的模块化编程,借助Angular路由机制实现了单页面的核心[3]。
SPA简单说就是一张页面替代传统网站多个页面跳转才能实现的功能。通过加载单个html页面同时在用户与应用程序交互式通过Ajax动态更新页面内容的应用。单页面应用开发设计技术较多且杂,包括HTML、CSS、LESS、JavaScript、MVC等,而Angular是一款优秀的JavaScript框架,支持MVC的架构编程模式[4]。同时它还具备很多特别且实用的功能,比如双向绑定、路由系统、指令系统、模块化、依赖注入等。
一个项目应用的可维护性和可拓展性很大程度上是和项目目录结构规划是否合理有很大关系的,本次项目是以外卖网站的附近店铺页面布局为基础,进行重现及单页面应用的研究改造和实现。如图1所示。
图1 目录结构规划
在图1中,app文件夹是项目的程序主入口文件,里面预期会由整个项目的核心javascript和angular来构成。css文件夹是网页样式的实现,font文件夹下主要是网站所需要的一些字体图标。imgs文件夹放的是网站需要的图片文件。json文件夹用来本地mock数据。index.html文件是程序入口页面。也就是单页面应用唯一需要的页面。
在编写代码中尽可能保证减少作用相同或者类似的代码重复出现,将相同的部分抽象出来,减少代码的冗杂。在angular中,要减少dom的操作,严格复用代码。通过指令组件化等方式减少代码的冗杂,整个程序在以angular构建时,严格按照其MVC的模式架构。做到三层分离,每次只需专注一层的东西,提高代码的质量和可拓展性同时减少后期的维护成本。
主页头部区域是页面主要的跳转菜单和登陆控件。头部在不同分辨率下宽度永远和浏览器宽度相等。主页主体区域经过测量宽度为1 180px,兼容了分辨率在1 180以上的电脑。主页头部区域通过一个div标签作为父级元素。设置width:100%和min-width:1 180px。再使用一个div通过margin:0 auto居中作为头部菜单的父级容器。头部跳转菜单和登录控件通过左右浮动分别固定在左右。主页主体区域的店铺列表使用一个div标签作为容器。设置宽度但是不设置高度,因为后期需要滚动加载所以不设置高度可以实现容器内塞下更多子元素展示店铺。所有的店铺都是用同规模div进行左浮动排列。在各店铺div中设置子div相对定位并隐藏实现悬浮详情的交互效果,搭载详细资料数据的div一样定宽不定高。尾部是加在更多功能区,使用一个长方形div构成和店铺列表容器是同级元素。排列方式根据块级元素的特性自动排列。实现效果如图2所示。
图2 主页主体店铺列表区域实现图
头部菜单的第一个主要交互是悬浮变色,专通过css3中的伪类:hover配合css的类选择器来实现。第二个主要交互是点击后的变色效果和hover效果的重置,通过angular的ng-class和ng-click来实现。首先给四个菜单各自定一个字符串用来识别当前我们点击的是哪一个。第三个主要交互是核心,确立头部菜单和主体区域的映射切换。使用ng-hide实现单页面切换。根据已有程序做添加即可。在model层中添加“ng-hide=相对应变量”,将每一个div作为每个头部菜单切换时对应的单页面看待,在controller的vm.negation中添加点击切换时对“相对应变量”进行改变的操作。第四个主要交互是因为最后一个菜单页拥有高度类似的html结构,而为了减少重复性和提高程序灵活性,需要做第四个隐式交互。
菜单分为一级菜单和二级菜单。一级菜单每一项对应一个二级菜单,每个二级菜单都是一个集合。而选择出哪个二级菜单则又决定了不同的店铺列表。这里可以使用多路由和子路由去实现。而子路由系统和多路由系统是原本的angular路由机制所不支持的,这里借助ui-router模块来实现,路由允许我们通过不同的 URL 访问不同的内容。路由也是实现单页Web应用的核心手段。比如通常URL地址为http://www.baidu.com/index,但单页面应用中路由可以支持通过#+标记实现(这种标记的专业名称叫做哈希)。这样地址就会变为http://www.baidu.com/index/menu1。而且在路由中不同的视图拥有对应且独立的controller这就为模块化提供了基础,借助路由可以构建更加健硕的应用程序,如图3所示。
图3 路由系统简图
传统的搜索功能通过遍历dom树节点用js比较。在angular中可以使用自定义filter根据条件过滤我们需要的数据来模拟搜索。首先实现自己的filter,其次解决多controller间的数据通信。根据angular数据的MVVM特性,搜索框的model绑定的变量就是搜索时的名称条件。在angular中,多controller通信则可以借助scope.broadcast去达到,如下:
vm.search = function () {
$scope.broadcast('changeSearch', vm.searchRes, 'search');
$rootScope.prevent = true;
};
传统网页的各项功能都是通过页面中的a标签跳转到一个新页面进行展现的。而单页面应用是将所有的功能都集中在一张页面上实现。性能测试可以通过比较二者之间实现同样功能速度间的差异来得到。通过谷歌开发者工具,可以看到单页面应用新页面的切换仅仅用了145 ms,而打开一张传统的页面根据大数据统计可以得知至少也需要1 s或者更长时间,如图4所示。
图4 切换新页面性能图
通过本次的单页面应用实现,我们可以发现单页面应用在当今的互联网产品迭代中所具有的优势。在长期的程序构建中,可以将不同的功能分成不同的模块,彼此之间不会相互影响。移除或者增加功能只需要删除或者添加新的模块即可。具备高内聚低耦合这个特性,也就是每个模块之间相互独立又相互关联的程序的可维护性是非常高的,相对来说这个应用程序的寿命就会很长和开发成本也会相对更低。