如何快速開發SPA應用

發表於2016-06-23

前言

web早已經進入了2.0時代了,如今的網頁大有往系統應用級別的方向發展的趨勢,再也不是以前的簡單展示資訊的介面了。如今很多webapp已經做到了原生應用的功能,並且運用自身的優勢逐步取代之。HTML5也很給力,對多平臺,多螢幕裝置的良好相容性使得前端工程師們在各種平臺上大顯身手。滷煮兩年前進公司接到的也是一個SPA應用的專案,也頗有些自己的心得,今日就寫篇博文,與大家分享下。

SPA

單頁 Web 應用 (single-page application 簡稱為 SPA) 是一種特殊的 Web 應用。它將所有的活動侷限於一個Web頁面中,僅在該Web頁面初始化時載入相應的HTML、JavaScript 和 CSS。一旦頁面載入完成了,SPA不會因為使用者的操作而進行頁面的重新載入或跳轉。取而代之的是利用 JavaScript 動態的變換HTML的內容,從而實現UI與使用者的互動。由於避免了頁面的重新載入,SPA 可以提供較為流暢的使用者體驗。得益於ajax,我們可以實現無跳轉重新整理,又多虧了瀏覽器的histroy機制,我們用hash的變化從而可以實現推動介面變化。從而模擬元素客戶端的單頁面切換效果:

優缺點

SPA被人追捧是有道理的,但是它也有不足之處。當然任何東西都有兩面性,以下是滷煮總結的一些目前SPA的優缺點:

優點:

1.無重新整理介面,給使用者體驗原生的應用感覺

2.節省原生(android和ios)app開發成本

3.提高發布效率,無需每次安裝更新包。這個對於ios開發人員來說印象尤其深吧。

4.容易藉助其他知名平臺更有利於營銷和推廣

5.符合web2.0的趨勢

缺點:

1.效果和效能確實和原生的有較大差距

2.各個瀏覽器的版本相容性不一樣

3.業務隨著程式碼量增加而增加,不利於首屏優化

4.某些平臺對hash有偏見,有些甚至不支援pushstate。(你懂的)

5.不利於搜尋引擎抓取

框架

一種開發模式火起來之後,對應的框架會隨之而起。像近幾年比較火的angularJS,是目前中最流行的mvvm框架,非常適合做SPA;與之類似的還有vueJS,滷煮在專案中也用過,相對於前者比較輕量。還有早一些的backbone,提供最基本的mvc模式,其他的模組大小和細節得自己決定。最早接觸的應該是extjs吧,這頭超級巨無霸在很早的時候被用來建立企業後臺應用,如今也跟著時代的變化做出了很多的改進。等等這些框架也好,庫也好,都旨在為了更好的構建SPA應用而生的,它們優缺點滷煮就不在此一一提了。

hash值

在此處提到一個比較重要的概念:URL中的井號。其實它只是瀏覽地址中的一個特殊符號。在以前,我們經常用它來定位文件位置。例如以下程式碼:

點選a連結,文件會滾動到id為target的div的可視區域上面去。hash除了這個功能還有另一一種含義:指導瀏覽器的行為但不上傳到伺服器。大家都知道,改變url中的任何一個字元都會導致瀏覽器重新請求伺服器,除了#號後面那段字元之外。所以,簡而言之我們可以這樣理解:改變#後面的值不觸發網頁過載,但會記錄到瀏覽器history中去。

實現原理

實現SPA的方法有很多,終歸一種遵循一種原則,介面無重新整理。如果要實現原生應用中類似許多不同頁面切換的效果,我們採用的是div切換顯示和隱藏。而驅動div顯示隱藏的方式有很多種

1.監聽位址列中hash變化驅動介面變化

2.用pushsate記錄瀏覽器的歷史,驅動介面傳送變化

3.直接在介面用普通事件驅動介面變化

前兩種方式較為普遍,因為它們的變化記錄瀏覽器會儲存在history中,可以通過回退/前進按鈕找回,或者history物件中的方法控制。最後一種方法是用普通事件驅動的,沒有改變瀏覽器的history物件,所以一旦使用者按了返回按鈕將會退到瀏覽器的主介面。所以,一般採用前兩種方式。值得一提的是,在不支援hash監聽和pushsate變化的瀏覽器中可以考慮用延時函式,不停得去監聽瀏覽器位址列中url發生的變化,從而驅動介面變化。

從零開始

滷煮在很久之前的一篇博文用pushstate的變化做了一個小小的示例,大家可以在之前的博文中找到它。在這裡,我們用監聽hash變化的方式展示SPA是怎麼樣執行工作的,同時從零開始,搭建一個基礎的SPA。幫助大家理解簡單的單介面應用的原理。

首先,我們畫出三個div,它們實際上是作為三個介面存在介面上的,body作為介面外框容器,限制著它們的大小。為了給每個介面配對一個hash地址,我們給每個div配一個id,講hash地址與對應的選擇器(id、class)建立連結關係,從而可以從hash變化值中操作介面。

接下來,為它們新增樣式,每個div都是全屏的,一開始只有A介面顯示,其他的都隱藏之:

現在我們給網頁新增上行為,首先需要知道的一點是,hash指即位址列中#號後面的字串,它的改變不會引起介面的重新整理,但是會出發onhashchange事件,我們要做的就是監聽這個事件:

目前,只需要以上的程式碼,我們便可以完成一個最簡單的SPA,通過位址列的變化,介面會相應地變化。當然,除了手動在位址列裡面改變hash的變化,我們也可以用程式碼改變它的變化,從而推動介面變化,下面是兩種方式的效果圖:

可以看到,左邊是在瀏覽器中直接修改hash引起了介面的變化,而右邊則是通過程式碼控制介面變化。這兩種方式都可以在history中留下痕跡,從而當我們店家回退/前進按鈕的時候追溯到之前的介面去。有些平臺不允許我們去手動修改位址列,(比如微信),那麼我們一般採用第二種方式即可。況且,比較少的使用者會去修改位址列。

下面貼出所有的程式碼:

SEO優化

由於我們在處理單頁應用的時候頁面是不重新整理的,所以會導致我們的網頁記錄和內容很難被搜尋引擎抓取到。搜尋引擎抓取頁面首先要遵循http協議,可是#不是協議內的內容。而實際上也是這樣,我們沒有見過搜尋引擎的搜尋結果中,哪一條記錄可以快速定位到網頁內的某個位置的。解決的方法是用 #!號代替#號,因為谷歌會抓取帶有#!的URL。(Google規定,如果你希望Ajax生成的內容被瀏覽引擎讀取,那麼URL中可以使用”#!”(這種URL在一般頁面一般不會產生定位效果)),這樣我們可以解決ajax的不被搜尋引擎抓取的問題。在vueJs裡面,我們可以看到作者就是這樣做的。

結束

以上就是利用hash原理實現的一個很簡單的SPA。當然,要實現專案中的單頁應用,還有很多工作要做。比如傳參,動畫,非同步資源載入的問題都是需要解決的。滷煮此處只是示範了一個很簡單的例子,希望在做不復雜又不想引入其他框架的同學提供一點思路。另外單頁雖好,但不要亂用哦,根據專案的具體需求制定對應的解決方案而不是一味的追潮逐流。

參考資料

相關文章