黃麗瓊, 李墨墨, 齊文豪
(商洛學(xué)院 數(shù)學(xué)與計(jì)算機(jī)應(yīng)用學(xué)院, 商洛 726000)
國際上,從2009年的Angular到2013年的React,再到2014年的Vue,各大以MVC為架構(gòu)模式,SPA(single page web application 單頁面應(yīng)用)為應(yīng)用核心的單頁面應(yīng)用框架應(yīng)運(yùn)而生[1-2]。本文通過html,less結(jié)合外賣平臺(tái)作為藍(lán)本搭建了單頁面應(yīng)用的功能表現(xiàn)載體——應(yīng)用主頁面,使用JavaScript的面向?qū)ο缶幊趟枷刖帉懥藦棿敖M件,利用Angular構(gòu)建了MVC的架構(gòu)模式,讓應(yīng)用實(shí)現(xiàn)視圖、模型、邏輯的分層,使用Angular命名空間、依賴注入以及JavaScript的閉包實(shí)現(xiàn)了應(yīng)用的模塊化編程,借助Angular路由機(jī)制實(shí)現(xiàn)了單頁面的核心[3]。
SPA簡單說就是一張頁面替代傳統(tǒng)網(wǎng)站多個(gè)頁面跳轉(zhuǎn)才能實(shí)現(xiàn)的功能。通過加載單個(gè)html頁面同時(shí)在用戶與應(yīng)用程序交互式通過Ajax動(dòng)態(tài)更新頁面內(nèi)容的應(yīng)用。單頁面應(yīng)用開發(fā)設(shè)計(jì)技術(shù)較多且雜,包括HTML、CSS、LESS、JavaScript、MVC等,而Angular是一款優(yōu)秀的JavaScript框架,支持MVC的架構(gòu)編程模式[4]。同時(shí)它還具備很多特別且實(shí)用的功能,比如雙向綁定、路由系統(tǒng)、指令系統(tǒng)、模塊化、依賴注入等。
一個(gè)項(xiàng)目應(yīng)用的可維護(hù)性和可拓展性很大程度上是和項(xiàng)目目錄結(jié)構(gòu)規(guī)劃是否合理有很大關(guān)系的,本次項(xiàng)目是以外賣網(wǎng)站的附近店鋪頁面布局為基礎(chǔ),進(jìn)行重現(xiàn)及單頁面應(yīng)用的研究改造和實(shí)現(xiàn)。如圖1所示。
圖1 目錄結(jié)構(gòu)規(guī)劃
在圖1中,app文件夾是項(xiàng)目的程序主入口文件,里面預(yù)期會(huì)由整個(gè)項(xiàng)目的核心javascript和angular來構(gòu)成。css文件夾是網(wǎng)頁樣式的實(shí)現(xiàn),font文件夾下主要是網(wǎng)站所需要的一些字體圖標(biāo)。imgs文件夾放的是網(wǎng)站需要的圖片文件。json文件夾用來本地mock數(shù)據(jù)。index.html文件是程序入口頁面。也就是單頁面應(yīng)用唯一需要的頁面。
在編寫代碼中盡可能保證減少作用相同或者類似的代碼重復(fù)出現(xiàn),將相同的部分抽象出來,減少代碼的冗雜。在angular中,要減少dom的操作,嚴(yán)格復(fù)用代碼。通過指令組件化等方式減少代碼的冗雜,整個(gè)程序在以angular構(gòu)建時(shí),嚴(yán)格按照其MVC的模式架構(gòu)。做到三層分離,每次只需專注一層的東西,提高代碼的質(zhì)量和可拓展性同時(shí)減少后期的維護(hù)成本。
主頁頭部區(qū)域是頁面主要的跳轉(zhuǎn)菜單和登陸控件。頭部在不同分辨率下寬度永遠(yuǎn)和瀏覽器寬度相等。主頁主體區(qū)域經(jīng)過測量寬度為1 180px,兼容了分辨率在1 180以上的電腦。主頁頭部區(qū)域通過一個(gè)div標(biāo)簽作為父級(jí)元素。設(shè)置width:100%和min-width:1 180px。再使用一個(gè)div通過margin:0 auto居中作為頭部菜單的父級(jí)容器。頭部跳轉(zhuǎn)菜單和登錄控件通過左右浮動(dòng)分別固定在左右。主頁主體區(qū)域的店鋪列表使用一個(gè)div標(biāo)簽作為容器。設(shè)置寬度但是不設(shè)置高度,因?yàn)楹笃谛枰獫L動(dòng)加載所以不設(shè)置高度可以實(shí)現(xiàn)容器內(nèi)塞下更多子元素展示店鋪。所有的店鋪都是用同規(guī)模div進(jìn)行左浮動(dòng)排列。在各店鋪div中設(shè)置子div相對(duì)定位并隱藏實(shí)現(xiàn)懸浮詳情的交互效果,搭載詳細(xì)資料數(shù)據(jù)的div一樣定寬不定高。尾部是加在更多功能區(qū),使用一個(gè)長方形div構(gòu)成和店鋪列表容器是同級(jí)元素。排列方式根據(jù)塊級(jí)元素的特性自動(dòng)排列。實(shí)現(xiàn)效果如圖2所示。
圖2 主頁主體店鋪列表區(qū)域?qū)崿F(xiàn)圖
頭部菜單的第一個(gè)主要交互是懸浮變色,專通過css3中的偽類:hover配合css的類選擇器來實(shí)現(xiàn)。第二個(gè)主要交互是點(diǎn)擊后的變色效果和hover效果的重置,通過angular的ng-class和ng-click來實(shí)現(xiàn)。首先給四個(gè)菜單各自定一個(gè)字符串用來識(shí)別當(dāng)前我們點(diǎn)擊的是哪一個(gè)。第三個(gè)主要交互是核心,確立頭部菜單和主體區(qū)域的映射切換。使用ng-hide實(shí)現(xiàn)單頁面切換。根據(jù)已有程序做添加即可。在model層中添加“ng-hide=相對(duì)應(yīng)變量”,將每一個(gè)div作為每個(gè)頭部菜單切換時(shí)對(duì)應(yīng)的單頁面看待,在controller的vm.negation中添加點(diǎn)擊切換時(shí)對(duì)“相對(duì)應(yīng)變量”進(jìn)行改變的操作。第四個(gè)主要交互是因?yàn)樽詈笠粋€(gè)菜單頁擁有高度類似的html結(jié)構(gòu),而為了減少重復(fù)性和提高程序靈活性,需要做第四個(gè)隱式交互。
菜單分為一級(jí)菜單和二級(jí)菜單。一級(jí)菜單每一項(xiàng)對(duì)應(yīng)一個(gè)二級(jí)菜單,每個(gè)二級(jí)菜單都是一個(gè)集合。而選擇出哪個(gè)二級(jí)菜單則又決定了不同的店鋪列表。這里可以使用多路由和子路由去實(shí)現(xiàn)。而子路由系統(tǒng)和多路由系統(tǒng)是原本的angular路由機(jī)制所不支持的,這里借助ui-router模塊來實(shí)現(xiàn),路由允許我們通過不同的 URL 訪問不同的內(nèi)容。路由也是實(shí)現(xiàn)單頁Web應(yīng)用的核心手段。比如通常URL地址為http://www.baidu.com/index,但單頁面應(yīng)用中路由可以支持通過#+標(biāo)記實(shí)現(xiàn)(這種標(biāo)記的專業(yè)名稱叫做哈希)。這樣地址就會(huì)變?yōu)閔ttp://www.baidu.com/index/menu1。而且在路由中不同的視圖擁有對(duì)應(yīng)且獨(dú)立的controller這就為模塊化提供了基礎(chǔ),借助路由可以構(gòu)建更加健碩的應(yīng)用程序,如圖3所示。
圖3 路由系統(tǒng)簡圖
傳統(tǒng)的搜索功能通過遍歷dom樹節(jié)點(diǎn)用js比較。在angular中可以使用自定義filter根據(jù)條件過濾我們需要的數(shù)據(jù)來模擬搜索。首先實(shí)現(xiàn)自己的filter,其次解決多controller間的數(shù)據(jù)通信。根據(jù)angular數(shù)據(jù)的MVVM特性,搜索框的model綁定的變量就是搜索時(shí)的名稱條件。在angular中,多controller通信則可以借助scope.broadcast去達(dá)到,如下:
vm.search = function () {
$scope.broadcast('changeSearch', vm.searchRes, 'search');
$rootScope.prevent = true;
};
傳統(tǒng)網(wǎng)頁的各項(xiàng)功能都是通過頁面中的a標(biāo)簽跳轉(zhuǎn)到一個(gè)新頁面進(jìn)行展現(xiàn)的。而單頁面應(yīng)用是將所有的功能都集中在一張頁面上實(shí)現(xiàn)。性能測試可以通過比較二者之間實(shí)現(xiàn)同樣功能速度間的差異來得到。通過谷歌開發(fā)者工具,可以看到單頁面應(yīng)用新頁面的切換僅僅用了145 ms,而打開一張傳統(tǒng)的頁面根據(jù)大數(shù)據(jù)統(tǒng)計(jì)可以得知至少也需要1 s或者更長時(shí)間,如圖4所示。
圖4 切換新頁面性能圖
通過本次的單頁面應(yīng)用實(shí)現(xiàn),我們可以發(fā)現(xiàn)單頁面應(yīng)用在當(dāng)今的互聯(lián)網(wǎng)產(chǎn)品迭代中所具有的優(yōu)勢。在長期的程序構(gòu)建中,可以將不同的功能分成不同的模塊,彼此之間不會(huì)相互影響。移除或者增加功能只需要?jiǎng)h除或者添加新的模塊即可。具備高內(nèi)聚低耦合這個(gè)特性,也就是每個(gè)模塊之間相互獨(dú)立又相互關(guān)聯(lián)的程序的可維護(hù)性是非常高的,相對(duì)來說這個(gè)應(yīng)用程序的壽命就會(huì)很長和開發(fā)成本也會(huì)相對(duì)更低。