移動端混合應用與響應式
前端是一個非常龐大和復雜的領域。
如果說多年前的前端只是需要學習幾個 HTML 標簽,看到別的網站用了狂拽酷炫的特效就 copy 下來,稍微懂點 jQuery 做日常使用,再了解幾個 Prototype 和 MooTools(貌似都不再維護了)等高冷脫俗的庫做裝X用就能顯得很“專家”了。那么現在要還是持這樣的想法,就不適合搞前端。
且不說 JavaScript 在與時俱進,更新出了 ES6,增加了茫茫多的特性,用 CSS 也可以做一些簡單動畫了。當一個新的 JS 庫或者框架發布時,它可能在 0.x 的版本就能火起一片天,又或者馬上出現競爭對手,多的是我們聽都沒聽過的工具。另一方面,連我們使用的設備也從 PC 的一統天下慢慢轉成了移動端的主場。
響應式與混合應用的概念
收,這篇文章的重點還是在于如何去考慮做移動端的響應式布局。
響應式(Responsive Web Design)是一個很早就出現的概念,當時人們就預想到 mobile 的占有率會飆升吧。 它指的是同一個頁面能夠適應不同尺寸的屏幕進行布局。 這里說尺寸是因為我們大部分時間是在關注屏幕大小,而不是它用的是多少比例的屏幕、設備的顏色深度等等,所以其他一些用途就沒必要說了,實行一下28原則吧(20% 的概念可以解決 80% 的問題)。
然后說 Hybrid 應用,它同樣不是一個新詞。很多專注于業務而非性能的 APP 都會采用這種方式去開發。它指的是用前端技術(HTML, CSS, JS)配合中間件(比如 cordova)去開發一個移動端應用。因為 WebView 的存在使這些都成為了現實。
它并不是什么高深的技術,只要稍微懂點英文單詞,根據它 官方文檔 描述的內容,花半天去看就能配出一個 apk 來了。
難的永遠不是框架或者工具,而是思考問題的角度和解決問題的方式。
畢竟從 apk 走到產品還是有很長一段路的。
屏幕尺寸
前端的同學應該對兼容性是恨透了,那做混合型應用的話就很少會有兼容性問題了,然而換來的卻是另一個問題——屏幕適配。
移動端屏幕尺寸的碎片化非常嚴重,小的有 320 * 480,大的有 1920 * 1080,然后你知道手機都支持旋轉的吧,所以這些尺寸的寬高對調一下又是一副新面孔。但只要有問題就有解決辦法,畢竟市面上那么多頁面都顯示的好好的,它們是怎么做到的呢?
喬布斯還活著的時候,他堅持認為 3.5 英寸的手機是最符合人體工學的,但我們知道,iphone 4s 比 iphone 3gs 的像素高。這是因為有個度量單位叫 PPI (Pixels per Inch) ,指的是每英寸的長度上有多少像素。
也就是說 320 * 480 的屏幕上一個像素,相當于 640 * 960 的屏幕上的四個像素。如果純粹按照像素來算的話,顯然后者可以在同樣大小的屏幕上顯示更多內容,這會導致有些內容甚至小到看不清。
縮放比例
我們希望對于同樣物理大小的屏幕,能有相同的布局,盡管他們的實際像素可能差幾倍。所以這里又有一個 倍率 的概念。之前提到響應式中的尺寸,就寬度來說的話,有兩種,一個是 width,另一個是 device-width 。前者是實際寬度,比如某手機屏幕的寬是 1080 像素;后者指的是按照倍率縮放之后的寬度,比如這款手機是 3 倍率的,那么 device-width 就是 360 像素了。
很多大屏手機,或者不同分辨率的手機,經過倍率的換算之后,device-width 是相當統一的。
所以這就是為什么我們會在手機端的頁面上設置如下標簽:
html<meta name="viewport" content="width=device-width, initial-scale=1">
就是為了讓 CSS 在設置大小(盒子寬高、行高、間距、字體大小等)時,按照 device-width 而不是實際像素來計算。
這樣子的話,同樣的頁面,在 1 倍率的 320 * 480 屏幕,和在 3 倍率的 960 * 1280 屏幕上會有一模一樣的布局。
至于如何計算這個縮放比例,很簡單,用
javascriptwindow.devicePixelRatio
一般桌面瀏覽器的 devicePixelRatio 是 1,手機上就會有 1.5, 2, 3 等值,然后與
javascriptscreen.width
結合換算一下就能得到我們需要適配的屏幕寬度了。
關于響應式布局的幾點建議
選擇斷點
首先需要明確的一點是,我們是 針對屏幕尺寸布局,而不是針對設備布局 。
所以,如果用 @media 做判斷的話,不需要針對 iphone 幾,或者 samsung 多少而無謂增加各種條件,只需要問自己,在 320 像素、360 像素、768 像素等寬度的屏幕中,頁面應該做怎樣的調整。
各位應該都知道,響應式布局中有一個“斷點”的概念,就是說,假設有
css@media (max-width: 768px) { /* 針對 768px 寬以下的屏幕 */ }
那么 768px 的寬度(如果在 meta 中設置了 width=device-width,這里的寬度就指的是 device-width)就是一個臨界點,小于等于 768px 的屏幕會執行這段 css,而大于 768 px 的屏幕就不會。
可能說屏幕大家會誤會,手機端的屏幕寬度就是視口(viewport)寬度,因為它不支持調整窗口大小,而 PC 端的瀏覽器可以調大小,那屏幕寬度確切地來說應該是視口寬度了,也就是網頁可視區域的寬度。
至于你應該怎樣去挑選斷點,就需要根據應用場景來決定了。我一般是開了 Firefox 的響應式設計模式,那里預置了很多尺寸,如果用戶對象是移動端,那么 360 * 640 就挺常見的。如果不知道應該怎么選的話,可以嘗試用一下。
利用 GPU 減少 DOM 操作
既然是做響應式,那么很多兼容性問題都不需要考慮了,畢竟只有 IE 9+ 才支持 @media 指令,那手機端就更不用說了。
CSS 3中新增了 transform 和 transition 這兩個和動畫相關的屬性。以往如果要實現將一個方框從 100 * 100 放大到 200 * 200,可能需要用 JS 去定時改變 style 中的 width 和 height 屬性,后果是每次 style 的改變都會引發 DOM 重繪。用 transition 可以這么來做:
css.box { width: 100px; height: 100px; transition: all ease-in .3s; } .box.active { width: 200px; height: 200px; }
需要放大的時候,通過 JS 給 .box 加上 active 類就可以了,GPU 會幫你完成過渡效果。當然,深入研究的話還有很多知識可以討論,只不過我想引出的就是, 能用 CSS 完成的效果就不要用 JS 去做 ,各司其職。
從另一個角度談性能
性能,經常看博客的同學可能都知道:壓縮 CSS 和 JS,做 sprite 圖,將圖片(要優化的話,圖片往往是重頭)部署到靜態資源服務器,用 CDN,等等。
但是那么多條條框框下,我們可以做到什么?對于很多前端工程師來說,這些事情是不需要自己去做的,公司中自然有專門的構建工具幫你部署。在學校中的同學,從來不會考慮這些方面,甚至沒有專門做前端的,就像本文開頭所說的,從別的網站上挪幾段樣式表過來。
然后,我們比較兩款產品,搜狗輸入法和QQ輸入法(好吧,雖然跟前端沒太大關系)。如果嘗試過各種輸入法的話,你會發現搜狗輸入法的啟動速度很慢。我無數次卸載過,換成必應輸入法、百度輸入法、QQ輸入法……但他們的皮膚都沒搜狗做的好,于是又可恥地裝了回來。
所以我覺得比性能更重要的產品特色。可能做前端的不會去多考慮產品相關的領域,但具體問題具體分析,不要為了刻意去提高性能而花很多工時在優化上。計算機界不是有句話很有名么:
過早的優化是萬惡之源。
并不是說不需要提高性能了,而是說,搞清楚什么時候該做什么事情。
倒是有些優化在編碼的時候就能做到的,就比如之前所說的利用 CSS 動畫而非 JS 去模擬。在用高級的 CSS 屬性時,想一想代價,能用低級的屬性就用低級的。意思就是說,用 flex 可以實現任何布局,但它的計算代價非常大,所以不到萬不得已就不用。
如果能保持一種代碼整潔的強迫感,那在優化這條路上就會走的很順暢吧。
(小結放到文章開頭了……)