在Vue項目中使用vw實現移動端適配

有關於移動端的適配佈局一直以來都是衆說紛紜,對應的解決方案也是有不少種。在《使用Flexible實現手淘H5頁面的終端適配》提出了Flexible的佈局方案,隨着viewport單位愈來愈受到衆多瀏覽器的支持,所以在《再聊移動端頁面的適配》一文中提出了vw來作移動端的適配問題。到目前爲止無論是哪種方案,都還存在必定的缺陷。言外之意,尚未哪個方案是完美的。css

事實上真的不完美?其實否則。最近爲了新項目中能更完美的使用vw來作移動端的適配。探討出一種能解決不兼容viewport單位的方案。今天整理一下,與你們一塊兒分享。若是方案中存在必定的缺陷,歡迎你們一塊兒拍正。html

準備工做

對於Flexible或者說vw的佈局,其原理不在這篇文章進行闡述。若是你想追蹤其中的原委,強烈建議你閱讀早前整理的文章《使用Flexible實現手淘H5頁面的終端適配》和《再聊移動端頁面的適配》。vue

說句題外話,因爲Flexible的出現,也形成不少同窗對rem的誤解。正如當年你們對div的誤解同樣。也所以,你們都以爲rem是萬能的,他能直接解決移動端的適配問題。事實並非如此,至於爲何,我想你們應該去閱讀flexible.js源碼,我相信你會明白其中的原委。html5

回到咱們今天要聊的主題,怎麼實現vw的兼容問題。爲了解決這個兼容問題,我將藉助Vue官網提供的構建工程以及一些PostCSS插件來完成。在繼續後面的內容以前,須要準備一些東西:node

對於這些起什麼做用,先不闡述,後續咱們會聊到上述的一些東西。webpack

使用Vue-cli來構建項目

對於NodeJsNPMWebpack相關介紹,你們能夠查閱其對應的官網。這裏默認你的系統環境已經安裝好Nodejs、NPM和Webpack。個人系統目前使用的Node版本是v9.4.0;NPM的版本是v5.6.0。事實上,這些都並不重要。ios

使用Vue-cli構建項目

爲了避免花太多的時間去深刻的瞭解Webpack(Webpack對我而言,太蛋疼了),因此我直接使用Vue-cli來構建本身的項目,由於我通常使用Vue來作項目。若是你想深刻的瞭解Webpack,建議你閱讀下面的文章:git

接下來的內容,直接使用Vue官方提供的Vue-cli的構建工具來構建Vue項目。首先須要安裝Vue-cli:github

 

全局先安裝Vue-cli,假設你安裝好了Vue-cli。這樣就可使用它來構建項目:web

 

根據命令提示作相應的操做:

進入到剛建立的vw-layout:

 

而後執行:

 

在瀏覽器執行http://localhost:8080,就能夠看以默認的頁面效果:

之前的版本須要先執行npm i安裝項目須要的依賴關係。如今新版本的能夠免了。

這時,能夠看到的項目結構以下:

使用Vue-cli構建項目

安裝PostCSS插件

經過Vue-cli構建的項目,在項目的根目錄下有一個.postcssrc.js,默認狀況下已經有了:

 

對應咱們開頭列的的PostCSS插件清單,如今已經具有了:

簡單的說一下這幾個插件。

postcss-import

postcss-import相關配置能夠點擊這裏。目前使用的是默認配置。只在.postcssrc.js文件中引入了該插件。

postcss-import主要功有是解決@import引入路徑問題。使用這個插件,可讓你很輕易的使用本地文件、node_modules或者web_modules的文件。這個插件配合postcss-url讓你引入文件變得更輕鬆。

postcss-url

postcss-url相關配置能夠點擊這裏。該插件主要用來處理文件,好比圖片文件、字體文件等引用路徑的處理。

在Vue項目中,vue-loader已具備相似的功能,只須要配置中將vue-loader配置進去。

autoprefixer

autoprefixer插件是用來自動處理瀏覽器前綴的一個插件。若是你配置了postcss-cssnext,其中就已具有了autoprefixer的功能。在配置的時候,未顯示的配置相關參數的話,表示使用的是Browserslist指定的列表參數,你也能夠像這樣來指定last 2 versions 或者 > 5%

如此一來,你在編碼時再也不須要考慮任何瀏覽器前綴的問題,能夠專心擼碼。這也是PostCSS最經常使用的一個插件之一。

其餘插件

Vue-cli默認配置了上述三個PostCSS插件,但咱們要完成vw的佈局兼容方案,或者說讓咱們能更專心的擼碼,還須要配置下面的幾個PostCSS插件:

要使用這幾個插件,先要進行安裝:

 

安裝成功以後,在項目根目錄下的package.json文件中,能夠看到新安裝的依賴包:

 

接下來在.postcssrc.js文件對新安裝的PostCSS插件進行配置:

 

特別聲明:因爲cssnextcssnano都具備autoprefixer,事實上只須要一個,因此把默認的autoprefixer刪除掉,而後把cssnano中的autoprefixer設置爲false。對於其餘的插件使用,稍後會簡單的介紹。

因爲配置文件修改了,因此從新跑一下npm run dev。項目就能夠正常看到了。接下來簡單的介紹一下後面安裝的幾個插件的做用。

postcss-cssnext

postcss-cssnext其實就是cssnext。該插件可讓咱們使用CSS將來的特性,其會對這些特性作相關的兼容性處理。其包含的特性主要有:

postcss-cssnext

有關於cssnext的每一個特性的操做文檔,能夠點擊這裏瀏覽

cssnano

cssnano主要用來壓縮和清理CSS代碼。在Webpack中,cssnanocss-loader捆綁在一塊兒,因此不須要本身加載它。不過你也可使用postcss-loader顯式的使用cssnano。有關於cssnano的詳細文檔,能夠點擊這裏獲取。

cssnano的配置中,使用了preset: "advanced",因此咱們須要另外安裝:

 

cssnano集成了一些其餘的PostCSS插件,若是你想禁用cssnano中的某個插件的時候,能夠像下面這樣操做:

 

上面的代碼把autoprefixerpostcss-zindex禁掉了。前者是有重複調用,後者是一個討厭的東東。只要啓用了這個插件,z-index的值就會重置爲1。這是一個天坑,千萬記得將postcss-zindex設置爲false

postcss-px-to-viewport

postcss-px-to-viewport插件主要用來把px單位轉換爲vwvhvmin或者vmax這樣的視窗單位,也是vw適配方案的核心插件之一。

在配置中須要配置相關的幾個關鍵參數:

 

目前出視覺設計稿,咱們都是使用750px寬度的,那麼100vw = 750px,即1vw = 7.5px。那麼咱們能夠根據設計圖上的px值直接轉換成對應的vw值。在實際擼碼過程,不須要進行任何的計算,直接在代碼中寫px,好比:

 

編譯出來的CSS:

 

在不想要把px轉換爲vw的時候,首先在對應的元素(html)中添加配置中指定的類名.ignore.hairlines(.hairlines通常用於設置border-width:0.5px的元素中):

 

寫CSS的時候:

 

編譯出來的CSS:

 

上面解決了pxvw的轉換計算。那麼在哪些地方可使用vw來適配咱們的頁面。根據相關的測試:

  • 容器適配,可使用vw
  • 文本的適配,可使用vw
  • 大於1px的邊框、圓角、陰影均可以使用vw
  • 內距和外距,可使用vw

postcss-aspect-ratio-mini

postcss-aspect-ratio-mini主要用來處理元素容器寬高比。在實際使用的時候,具備一個默認的結構

 

在實際使用的時候,你能夠把自定義屬性aspectratioaspectratio-content換成相應的類名,好比:

 

我我的比較喜歡用自定義屬性,它和類名所起的做用是同等的。結構定義以後,須要在你的樣式文件中添加一個統一的寬度比默認屬性:

 

若是咱們想要作一個188:246188是容器寬度,246是容器高度)這樣的比例容器,只須要這樣使用:

 

有一點須要特別注意:aspect-ratio屬性不能和其餘屬性寫在一塊兒,不然編譯出來的屬性只會留下aspect-ratio的值,好比:

 

編譯前的CSS以下:

 

編譯以後:

 

主要是由於在插件中作了相應的處理,不在每次調用aspect-ratio時,生成前面指定的默認樣式代碼,這樣代碼沒那麼冗餘。因此在使用的時候,須要把widthbackground-color分開來寫:

 

這個時候,編譯出來的CSS就正常了:

 

有關於寬高比相關的詳細介紹,若是你們感興趣的話,能夠閱讀下面相關的文章:

目前採用PostCSS插件只是一個過渡階段,在未來咱們能夠直接在CSS中使用aspect-ratio屬性來實現長寬比。

postcss-write-svg

postcss-write-svg插件主要用來處理移動端1px的解決方案。該插件主要使用的是border-imagebackground來作1px的相關處理。好比:

 

編譯出來的CSS:

 

上面演示的是使用border-image方式,除此以外還可使用background-image來實現。好比:

 

編譯出來就是:

 

解決1px的方案除了這個插件以外,還有其餘的方法。能夠閱讀前期整理的《再談Retina下1px的解決方案》一文。

特別聲明:因爲有一些低端機對border-image支持度不夠友好,我的建議你使用background-image的這個方案。

CSS Modules

Vue中的vue-loader已經集成了CSS Modules的功能,我的建議在項目中開始使用CSS Modules。特別是在Vue和React的項目中,CSS Modules具備很強的優點和靈活性。建議看看CSS In JS相關的資料。在Vue中,使用CSS Modules的相關文檔能夠閱讀Vue官方提供的文檔《CSS Modules》。

postcss-viewport-units

postcss-viewport-units插件主要是給CSS的屬性添加content的屬性,配合viewport-units-buggyfill庫給vwvhvminvmax作適配的操做。

這是實現vw佈局必不可少的一個插件,由於少了這個插件,這將是一件痛苦的事情。後面你就清楚。

到此爲止,有關於所須要的PostCSS已配置完。而且簡單的介紹了各個插件的做用,至於詳細的文檔和使用,能夠參閱對應插件的官方文檔。

vw兼容方案

在《再聊移動端頁面的適配》一文中,詳細介紹了,怎麼使用vw來實現移動端的適配佈局。這裏不作詳細的介紹。建議你花點時間閱讀這篇文章。

先把未作兼容處理的示例二維碼貼一個:

你可使用手淘App、優酷APP、各終端自帶的瀏覽器、UC瀏覽器、QQ瀏覽器、Safari瀏覽器和Chrome瀏覽器掃描上面的二維碼,您看到相應的效果:

但還有不支持的,好比下表中的No,表示的就是不支持

品牌 型號 系統版本 分辨率 屏幕尺寸 手淘APP 優酷APP 原生瀏覽器 QQ瀏覽器 UC瀏覽器 Chrome瀏覽器
華爲 Mate9 Android7.0 1080 x 1920 5英寸 Yes Yes No Yes Yes Yes
華爲 Mate7 Android4.2 1080 x 1920 5.2英寸 Yes Yes No Yes Yes Yes
魅族 Mx4 (M460 移動4G) Android4.4.2 1152 x 1920 5.36英寸 Yes No No Yes Yes Yes
Oppo R7007 Android4.3 1280 x 720 5英寸 Yes No No Yes Yes No
三星 N9008 (Galaxy Note3) Android4.4.2 1080 x 1920 5.7英寸 Yes No Yes Yes Yes Yes
華碩 ZenFone5(x86) Android4.3 720 x 280 5英寸 No No No Yes No No

正因如此,不少同窗都不敢嘗這個螃蟹。懼怕去處理兼容性的處理。不過沒關係,今天我把最終的解決方案告訴你。

最終的解決方案,就是使用viewport的polyfill:Viewport Units Buggyfill。使用viewport-units-buggyfill主要分如下幾步走:

引入JavaScript文件

viewport-units-buggyfill主要有兩個JavaScript文件:viewport-units-buggyfill.jsviewport-units-buggyfill.hacks.js。你只須要在你的HTML文件中引入這兩個文件。好比在Vue項目中的index.html引入它們:

 

你也可使用其餘的在線CDN地址,也可將這兩個文件合併壓縮成一個.js文件。這主要看你本身的興趣了。

第二步,在HTML文件中調用viewport-units-buggyfill,好比:

 

爲了你Demo的時候能獲取對應機型相關的參數,我在示例中添加了一段額外的代碼,估計會讓你有點煩:

 

具體的使用。在你的CSS中,只要使用到了viewport的單位(vwvhvminvmax )地方,須要在樣式中添加content

 

這可能會令你感到噁心,並且咱們不可能每次寫vw都去人肉的計算。特別是在咱們的這個場景中,我們使用了postcss-px-to-viewport這個插件來轉換vw,更沒法讓咱們人肉的去添加content內容。

這個時候就須要前面提到的postcss-viewport-units插件。這個插件將讓你無需關注content的內容,插件會自動幫你處理。好比插件處理後的代碼:

Viewport Units Buggyfill還提供了其餘的功能。詳細的這裏不闡述了。可是content也會引發必定的反作用。好比img和僞元素::before(:before)或::after:after)。在imgcontent會引發部分瀏覽器下,圖片不會顯示。這個時候須要全局添加:

 

而對於::after之類的,就算是裏面使用了vw單位,Viewport Units Buggyfill對其並不會起做用。好比:

 

這個時候咱們須要經過添加額外的標籤來替代僞元素(這個情景我沒有測試到,後面本身親測一下)。

到了這個時候,你就不須要再擔憂兼容問題了。好比下面這個示例:

請用你的手機,無論什麼APP掃一掃,你就能夠看到效果。(當心彈框喲),若是你發現了仍是有問題,請把彈出來的信息截圖發給我。

如查你想看看別的機型效果,能夠點擊這裏這裏這裏、還有這裏。整個示例的源碼,能夠點擊這裏下載

若是你下載了示你源碼,先要確認你的系統環境能跑Vue的項目,而後下載下來以後,解壓縮,接着運行npm i,再運行npm run dev,你就能夠看到效果了。

總結

若是你看到這裏了,但願這篇文章對你有所幫助。能幫助你解決項目中的實際問題,讓你再也不擔憂移動端的適配問題。固然更但願的是你在實際的項目中用起這個方案,把碰到的問題及時反饋給偶。若是你有更好的方案,歡迎在下面的評論中與咱們一塊兒分享。

著做權歸做者全部。
原文: https://www.w3cplus.com/mobile/vw-layout-in-vue.html © w3cplus.com

相關文章
相關標籤/搜索