這段時間在作的東西,是北郵人論壇APP的註冊頁。這個註冊頁是內嵌的網頁,由於打算安卓和IOS平臺同時使用。所以實際上就是在作移動端的web開發了。
在這過程當中遇到了很多有意思的東西。php
DEMO的github地址在這裏css
內容提要:
html
這點與在PC端寫前端有着很大的區別,移動端的meta標籤簡直多。我就說說我所用到的標籤。前端
<!-- 一、若是支持Google Chrome Frame:GCF,則使用GCF渲染;二、若是系統安裝ie8或以上版本,則使用最高版本ie渲染;三、不然,這個設定能夠忽略。 --> <meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1"> <!-- 對視窗縮放等級進行限制,使其適應移動端屏幕大小 --> <meta name="viewport" content="width=device-width, initial-scale=1"> <!-- 當把這個網頁添加到主屏幕時的標題(僅限IOS) --> <meta name="apple-mobile-web-app-title" content="北郵人論壇註冊"> <!-- 添加到主屏幕後全屏顯示 --> <meta name="apple-touch-fullscreen" content="yes" />
尤爲是第二個meta標籤,是移動端適配很是重要的一句話。vue
總體的佈局大體是4-5頁橫向佈局。第一頁是用來填寫註冊信息的。後面的幾頁是用來選擇關注的版面的。
jquery
前端採用的架構大體是這樣:
css3
後端支撐的框架來自php的laravel,固然,這不是本文的重點,僅說起一下。laravel
是的此次的開發中,已經看不到jquery的身影了——這也是前端之後發展後的結果——慢慢地脫離jquery的依賴。不過jquery給前端帶來的改變和發展是無人能替代的。git
引入swiper.js來進行頁面的切換效果純粹是由於此次開發的週期要求比較短,要考慮效果和兼容性兼備的狀況下,我就偷懶找了一個動畫庫。github
不過這個動畫庫的效果我仍是算比較滿意的。而總體來講使用也至關方便。尤爲是,swiper.js是能夠不依賴jquery的。
使用起來也比較方便。我簡要說說用法。
首先須要在頁面頂部的head標籤里加入swiperjs的css文件:
<link rel="stylesheet" href="css/swiper.min.css')">
而後在頁面底部能夠引入和寫下相應的js:
<script src="{{ asset('js/swiper.min.js') }}"></script> <!-- Initialize Swiper --> <script> var swiper = new Swiper('.swiper-container', { pagination: '.swiper-pagination', paginationType: 'progress', noSwipingClass: 'swiper-no-swiping', allowSwipeToNext: true, allowSwipeToPrev: true, }); </script>
解釋一下,建立一個swiper的對象,而後這對象的容器是class叫作swiper-container的一個html元素。對其的配置是:
相應的HTML代碼能夠以下:
<!-- swiper生效的容器 --> <div class="swiper-contanier"> <div class="swiper-wrapper"> <!-- 具體滑動的頁面 --> <div class="swiper-slide"></div> <div class="swiper-slide"></div> <div class="swiper-slide"></div> <div class="swiper-slide"></div> </div> </div> <!-- 進度條 --> <div class="swiper-pagination"></div>
有些頁面是不能直接讓用戶經過觸摸來先後滑動的,而必須經過點擊按鈕觸發。好比第一頁註冊頁,這個頁面就是必須填寫完信息而後點擊下一步進行驗證後而後才能夠滑動到後面的內容。因此只要將這個頁面所在的class里加上swiper-no-swiping這個class就能夠實現沒法觸摸滑動切換頁面了。
而後咱們能夠經過swiper.slideNext(bool,time)這個方法來進行手動控制向後翻頁的動做以及控制動畫的時長。這個內容會在vue裏說到。
因爲本次的開發只是在原有的北郵人開放平臺的項目的基礎上加入一個快速註冊的功能,因此Vue.js的引入並非爲了將整個項目重構,而只是爲了嘗試一下脫離jquery的狀況下對於開發來講不一樣的體驗是什麼,能學到什麼。
關於Vue.js的用法、特性什麼的不是本文的重點,題外話就不說了。說說本次實現思路。由於個人Vuejs實際上也只是算入門級別,只能說會用可是還沒到能駕馭的程度。
首先整個頁面包在class叫作swiper-contanier的元素中。由於這個元素包括了滑動所需的全部東西,咱們實際上能夠簡單的把它當作是一個SPA(Single Page Application),用一個Vue的實例就能夠接管整個頁面了(這麼說是不負責的,由於實際上Vue是組件化的思想)。
先建立一個基本的Vue的示例,並將其和swiper-container綁定起來:
var vm = new Vue({ el: ".swiper-contanier", // 將這個實例與html元素綁定起來 data: {}, // 所須要變更、關注的數據,也是vue的核心 ready: function(){}, // vue提供的鉤子,用於在vue渲染視圖完成後當即觸發 methods: {} // 方法,用於操做、更新、改變數據而改變視圖 })
上面所說,咱們的頁面是構建在一個Vue的實例上的。所以不一樣類型的兩種頁面如何用一個實例來接管呢?在這裏個人實現方式是用兩類數據來分別表示。
咱們分析一下注冊頁:
實際上註冊頁的中間部分是重複的元素,他們都是input標籤+顯示文字標籤(對,尤爲注意這裏並非用placeholder實現的)。效果:
因此這中間的部分實際上能夠當作是一個列表,能夠用Vue的v-for來渲染。列表裏所不一樣的只是顯示的文字不一樣以及input框的類型不一樣(有text類型的,有password類型的),因此用數據綁定的方式咱們能夠將這個頁面的數據格式安排以下:
data: { main: [ {"name":"username","info":"用戶名(以英文開頭+英文數字)","type":"text"}, {"name":"passwd","info":"設置密碼","type":"password"}, {"name":"passwd_confirm","info":"在輸入一遍密碼","type":"password"}, {"name":"gwno","info":"校園網帳戶(默認是學號)","type":"text"}, {"name":"gwpwd","info":"校園網密碼(默認是身份證後六位)","type":"password"}, ], }
同時咱們建立一個便於和前端視圖進行雙向綁定的數據對象userInfo:
data: { main: [...], userInfo: { username: "", passwd: "", passwd_confirm: "", gwno: "", gwpwd: "" } }
而在前端的話咱們就能夠用這個數據來進行視圖渲染:
<ul class="user-info"> <li v-for="item in main" style="position: relative;"> <!-- input輸入框 --> <!-- 此處用了v-model將數據和視圖進行了雙向綁定 --> <input class="effect" type="{{item.type}}" v-model="userInfo[item.name]"> <!-- 提示信息 --> <label> <span>{{item.info}}</span> </label> <!-- input框的底下的線條 --> <span class="focus-border cube"></span> </li> </ul> <a href="#"><button>下一步</button></a>
因而一個輸入的列表就很容易作出來了。而後既然是表單,就須要驗證。而此處作的驗證明際上有這麼幾點:
其中只有第二點兩次密碼輸入是否相同能夠用前端直接判斷,而第1、三點都是須要經過ajax的方式向後臺發送驗證請求的。爲了可以體現和辨別錯誤與否,咱們在main下的每一個條例里加入了一個error屬性,並規定以下三種狀態:
因而咱們能夠在method下寫一些方法來進行判斷。
checkUserId: function(msg){ if (msg !== ""){ this.$http.post('url'+msg,function(data){ if (data.success){ this.main[0].error = false; } else{ this.main[0].error = true; } }) } else{ this.main[0].error = "normal"; } }, checkUserPwd: function(){ if (this.userInfo.passwd_confirm !== ""){ this.userInfo.passwd == this.userInfo.passwd_confirm && this.userInfo.passwd_confirm != "" ? this.main[2].error = false : this.main[2].error = true; } },
固然這個只是一個引入的功能,咱們再聚合一下:
check: function(msg,i){ var index = i; this.userInfo[msg] != "" ? this.main[index].effect = true : this.main[index].effect = false; switch (msg){ case "username": this.checkUserId(this.userInfo[msg]); break; case "passwd": this.userInfo.passwd !== "" ? this.main[1].error = false : this.main[1].error = "normal"; this.checkUserPwd(); break; case "passwd_confirm": this.checkUserPwd(); break; case "gwno": this.userInfo.gwno !== "" ? this.main[3].error = false : this.main[3].error = "normal"; break; case "gwpwd": this.userInfo.gwno !== "" ? this.main[4].error = false : this.main[4].error = "normal"; break; } }
這樣經過一個check的method咱們就能夠將整個表單的驗證的方法容納進來了。(此處對於校園網帳號的驗證會放到提交表單的函數中)。爲了能在視圖中體現正確、錯誤、正常的不一樣形態,咱們須要對前端的一些結構進行一些修改。咱們須要給main下的每一個條例加入錯誤信息,也即errorInfo。
因此至此整個main的結構是這樣:
main: [ {"name":"","info":"","type":"","error":"","errorInfo":""}, ... ]
而後咱們須要加入提交驗證的部分:
submitReg: function(){ var flag = 0; // 用於判斷表單是否都是正確的 this.main.map(function(obj){ obj.error == false ? flag += 1 : flag +=0; }) if (flag == 5){ this.$http.post('url',this.userInfo) .then(function(res){ if (res.success){ swiper.slideNext(false,300); // 驗證正確就能夠進入下一頁 } else{ this.main[4].error = true; } }) } },
將視圖部分修改以下:
<ul class="user-info"> <li v-for="item in main" style="position: relative;"> <!-- 綁定blur事件 --> <input @blur="check(item.name,$index)" class="effect" type="{{item.type}}" v-model="userInfo[item.name]"> <!-- 根據error類型切換不一樣的標籤顯示 --> <label> <!-- 此處用到了v-show的方法 --> <span v-show="item.error == 'normal'">{{item.info}}</span> <span style="color: red;" v-show="item.error == true">{{item.errorInfo}}</span> <span v-show="item.error == false">{{item.info}}√</span> </label> <span class="focus-border cube"></span> </li> </ul> <!-- 點擊下一步的同時提交表單信息 --> <a href="#"><button @click="submitReg">下一步</button></a>
至此,整個註冊頁的佈局和功能性的部分都已經作完了。不過這只是一塊比較簡單的部分,咱們用到了vuejs的的v-for進行列表渲染,用到了v-model進行數據的雙向綁定,用到了method進行一些數據的處理,用到了v-show進行條件顯示,一個基本的頁面下咱們已經能嘗試這麼多vue的特性了。而相比於jquery的dom操做,我以爲vue在此處最好的地方在於,表單的提交很方便。因爲雙向綁定了數據,只須要後臺把數據格式規定好給我,我按照後端的數據結構整理一下我前端的數據結構而後就能夠直接提交給後端了。並且省去了不少dom操做的地方。
不過除了vue的部分,我還想來講說兩個東西,跟css有關:
全屏背景
不只僅是簡單的background-size: cover那麼簡單了,還須要進行小小的處理。先說說我但願實現的效果吧。我但願的效果是整個背景可以填充整個頁面,而且在頁面元素上下滾動的狀況下,背景固定而不隨着元素滾動。
放到往常我可能會這麼寫:
body,html{ height: 100%; } body{ background: url(bg.png) center 0 no-repeat; background-size: cover; }
可是這樣的話在移動端會出現比較嚴重的後果,那就是一旦頁面元素的高度大於整個頁面後,滾動頁面元素的時候,背景也會隨之而動。並且背景會被撐開。這不是我所但願的。
這裏用到一個小技巧,用上:before的方法。
body:before { content: ""; position: fixed; z-index: -1; top: 0; right: 0; bottom: 0; left: 0; background: url(bg.png) center 0 no-repeat; background-size: cover; }
這個用上before的僞元素的方法是一個頗有奇效的小技巧。你們不妨能夠試試。這樣的話在移動端也能完美實現背景固定並且顯示全屏。
移動端動畫簡單初探
在作PC端的web的動畫效果的時候,因爲PC端的性能足夠,因此在寫一些效果的時候每每沒有考慮到性能的問題。此次在開發的時候就遇到了動畫效果實現上不小的問題。你們先來看看這兩個動畫的比較:上面一個動畫和下面一個動畫:
第一個:
https://codepen.io/molunerfinn/pen/zBGrxx
第二個:
https://codepen.io/molunerfinn/pen/oLXjKz
會發現這兩個東西的效果相差甚大。實際上,兩者實現的最終效果是一致的,都是讓小球按一條口型路線運動。可是爲什麼顯示上來講,第一個這麼流暢,而第二個有明顯卡頓呢?
這裏涉及到不少東西,不光光是重繪(repaint),還有軟硬件性能上面的問題。感興趣的話能夠參考這些文章:
在移動端上的效果若是沒有優化的話,實際上大體就是第二種的效果——讓人看起來有所卡頓。簡單來講,在移動端,有些效果是由瀏覽器來渲染的——那麼這些效果若是比較複雜,而移動端的瀏覽器性能又不太足夠的狀況下,效果就比較卡頓。有些效果能夠由GPU來渲染,那麼這些效果渲染起來就相對來講比較流暢。而咱們還能夠人爲觸發GPU硬件渲染,經過 transform的translate3d屬性就能實現硬件渲染從而俗稱硬件加速。
舉個簡單例子。若是讓一個元素從(0,0)->(100px,0),正常思路是left: 0->left: 100px,而後再用transition屬性進行過渡。不過這樣的話在移動端上效果就很感人,由於涉及到性能問題。可是若是咱們用另一種方式: transform: translate3d(100px,0,0)的話,就可讓這個動畫效果由GPU去渲染,那麼這樣的話,在移動端的效果也是徹底能夠接受的流暢。
實際上,可以觸發GPU渲染的動做有opacity,transform,transition,animation等等。可是像top,left,color,size等屬性的變化則不會觸發GPU渲染。
本文中描述的實例,是當焦點集中到input框的時候,文本上移而且有顏色變化。原本想實現的是文本大小還有變化。可是因爲上面說的狀況,涉及到size變化的時候,效果就會大打折扣。無奈之下我只能砍掉這個效果了。而實現文本上移實際上就是採用了transform的translate3d的方式,將其往上移動,並配合transition進行了一下過渡處理罷了。
具體的CSS實現大體以下:
input:focus ~ label,.trans { color: #fff; transition: 0.3s; -webkit-transform: translate3d(0, -20px, 0); -moz-transform: translate3d(0, -20px, 0); -ms-transform: translate3d(0, -20px, 0); transform: translate3d(0, -20px, 0); }
實際上也不難不是麼?
實際上從註冊頁的實現中已經能夠瞅見關注版面頁實現的方法了。實際上關注版面頁不過也是列表的渲染,在數據裏定義好相應的屬性就好了。而後用一個picked的屬性來看看是否被選中便可。最後完成註冊的時候,將全部選中的列表組裝成相應的數組提交到後臺就好了。由於註冊頁裏這些方法已經說過了,因此就再也不贅述了。
實際上,兼容性方面還有很多的東西須要訴說,不過限制於篇幅以及本文的主要內容並非在糾結移動端的兼容性的因此並無在兼容性方面進行記錄。
在排版上我仍是沒有用上比較流行的flex,對於Vue尚未使用組件化開發的思路。這些都是須要改進的部分。不過此次的開發過程當中通過美工的指點,將我以前寫頁面的時候注意不到的不少細節部分,好比線條尺寸,元素間隔,顏色搭配等東西給指了出來,這些東西都不是簡簡單單就實現的。總之,有時間的話,我想我能夠將設計方面的知識融入到個人前端開發中,想必能讓個人做品更加地符合審美和用戶的體驗吧~
DEMO的github地址在這裏
文章做者: Molunerfinn
文章連接: https://molunerfinn.com/vuejs-1/
版權聲明: 本博客全部文章除特別聲明外,均採用 CC BY-NC-SA 4.0 許可協議。轉載請註明來自 MARKSZのBlog!