用Vue開發仿旅遊站webapp項目總結 (上)

寫着寫着發現會寫很多內容... 所有寫在一篇文章裏感受太多了不方便看,因此分爲上下篇吧...

下篇寫完啦,感興趣的朋友能夠繼續關注 => Vue開發仿旅遊站webapp項目總結 (下)css

舒適提示

此文章,僅是作完項目後的我的以爲能夠總結下來的操做/思路,接觸vue不久的朋友應該會有收穫。此項目也纔是萌新作的第二個Vue項目,使用了腳手架工具( vue-cli 2.x 非 3 ),前輩老手們有時間看的話,有寫得很差的地方還請多多指導!~html

成果預覽

僅實現項目首頁、項目詳情頁、城市列表頁組件的頁面/邏輯。vue

千萬別點我webpack

項目初始化

先用腳手架生成項目框架。ios

由於作的是一個移動端網頁,因此咱們能夠有一些配置:git

第一步 配置meta標籤

index.html里加個 meta 標籤:github

<meta name="viewport"content="width=device-width,initial-scale=1.0,
    minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">

在網頁的<head>標籤中增長以上代碼,可讓網頁的寬度自動適應手機屏幕的寬度。web

其中:ajax

width=device-width : 表示寬度是設備屏幕的寬度vuex

initial-scale=1.0 : 表示初始的縮放比例

minimum-scale=1.0 : 表示最小的縮放比例

maximum-scale=1.0 : 表示最大的縮放比例

user-scalable=no : 表示用戶是否能夠調整縮放比例

以上我設置的參數的目的是:想要一打開網頁,就自動以原始比例顯示,而且不容許用戶修改,不容許用戶縮放。

第二步 初始化默認樣式

在不一樣的手機瀏覽器上,默認的一些樣式是不一樣統一的。咱們須要把這些不一樣手機的初始化樣式作一個統一。

因此能夠引入個 reset.css

這是一個初始化的代碼,其中一些初始化配置能夠自行根據需求修改。

想看/拿代碼的能夠到我Github上拿:src/assets/styles/reset.css

第三步 解決1像素邊框方案

在移動端頁面開發,經常有個 1像素邊框 的問題。

也就是有的手機屏幕分辨率比較高,若是咱們在頁面上寫border-bottom啥的樣式,會致使這些手機屏幕分辨率高的當中,1px邊框顯示成2px邊框或3px邊框等顯示成多像素。

爲了解決這個1像素邊框問題,咱們就引入了 border.css(貌似這是哪一個團隊提出的解決方案?忘記啦,只知道怎麼用...但仍然要表示感謝。還有其餘解決方案,這個就自行搜索了。)

兩百多行不貼出來了,想看/拿完整代碼的能夠到我Github上:src/assets/styles/border.css

具體這個解決方案的用法,看過border.css代碼的同志就會發現很簡單:在元素上根據想要的需求加如下這些類名。

按照字面意思理解就行。

好比要給一個元素加上一像素的下邊框,就直接加個類名:<div class="border-bottom>"就好了。

要給一個元素加上一像素的上邊框和下邊框,就直接加類名:<div class="border-topbottom">就好了。

邊框也能夠改顏色的,舉個項目中的例子,按照這種格式去改顏色(本文例子有css代碼的話基本都是stylus的寫法):

對應頁面:

第四步 引入fastclick庫

在移動端開發中,某些機型、某些瀏覽器上,click點擊事件要延遲300ms執行。

要解決這個問題,咱們引入個fastclick庫

npm install fastclick --save

--save的意思是:無論在開發環境測試,仍是線上跑代碼,安裝了的庫均可以使用。而且下載好後,自動存到package.json的dependencies屬性中,好比這裏install的fastclick:

而後在入口函數main.js中引入和使用:

import fastClick from 'fastclick'
fastClick.attach(document.body)

第五步 配置使用iconfont

先在阿里巴巴矢量圖標庫建立一個項目

而後在iconfont上選購,添加到購物車,選好後添加到本身的項目,而後下載到本地。

下載的東西中只要用到這幾個:

而後把iconfont.css放到一個文件夾中而且在入口函數main.js處引入後就能夠全局使用了。

舉個使用的例子:

注意類名要加iconfont,而後這裏在span裏輸入的代碼就是你選中的圖標的代碼:

第六步 自定義目錄

這步其實應該穿插在作項目過程當中進行的,這裏先列出來。

在build文件夾下的webpack.base.conf.js中配置,以下圖,圈起來的是我在項目中配置的。

這樣有配置後就可使用自定義目錄了。好比按照我上面的配置的話

import src/assets/styles/border.css

就能夠寫成

import styles/border.css了。

首頁開發中想記錄下來的

輪播插件

安裝與使用

這裏使用的是 vue-awesome-swiper。

先安裝: npm install vue-awesome-swiper --save

而後用法一些的其實均可以在其文檔中查閱到:


鑑於在各個頁面均可能會用到輪播功能,因此直接在全局也就是入口文件 main.js 處引入。

而後使用:

好比要使用按鈕區的話,就須要配置參數。根據我的在項目中的需求,能夠查閱其github文檔按需使用。

這裏值得一提的是:假如在輪播圖的下面有東西

好比這個test。在網速慢慢加載的時候,可能test會先在上面顯示,而後等圖片撐開區域的時候再跑回下面。

爲了防止這種抖動,最好這樣子作:

給輪播swiper外面套一層類爲wrapper的div,而後給div固定大小。好比在項目中這裏的輪播圖片的寬高比是 364:97 約等於 3.75,高度是寬度的百分之 26.6。

因此響應式開發能夠這樣給div框樣式:


如今vw單位的兼容性其實能夠了。

有種兼容性很好的方案:

overflow: hidden
width: 100%
height: 0
padding-bottom: 26.6%

這種方式也是高度是寬度的 26.6%。

其實吧。。這個vue-aowsome-swiper組件目前爲止已經不存在這種抖動問題了。。

還有個改變插件默認顏色的問題

好比插件按鈕區配置後,默認按鈕顏色是藍色小圓點。

審查元素能夠看出:

那咱們以下這樣子加樣式去改變行嗎?

通常這樣子問都是不行滴...

由於有scoped做用域的緣由,這個類的屬性的設置是在本來的 swiper組件下,而不是在咱們這裏設置的swiper組件下。

應該這樣設置:

意思是在.wrapper下的全部類中,找.swiper-pagination-bullet-active類。

>>>是具備穿透做用域的意思,穿透其餘組件的做用域。

若是文字在一行中多了,實現省略號效果

好比,這裏是個p標籤。

P標籤裏的數據太多的話 但願顯示一個 ... 省略號。

能夠這樣利用text-overflow屬性:

要實現溢出時產生省略號的效果,應該在定義兩個樣式:強制文本在一行內顯示(white-space:nowrap)和溢出內容爲隱藏(overflow:hidden),只有這樣才能實現溢出文本顯示爲省略號效果。

發送ajax請求

通常狀況下在mounted鉤子裏發送ajax請求數據。想詳細瞭解生命週期 => 我有寫過一篇文章

請求方式,看本身,這個項目中axios、fetch兩個方式我都寫過。

配置

首先,用vue腳手架工具生成的工程裏面,只有static目錄(靜態文件目錄)下,才能被外界訪問到。

咱們就把本地的一些模擬數據放在這個static目錄下,本身建個文件夾存儲數據。這個項目中是static/mock/index.json:

這數據是本地的模擬數據,咱們不但願到時候一塊兒把它push到線上,能夠在.gitignore裏這樣配置:

如今這個文件夾下的全部東西都不會被傳到線上了。

固然,也不會提交到本地的git倉庫裏面。

這樣配置還不夠,目前在局部根組件中寫的請求的路徑是這樣的,拿項目中舉例:

當咱們上線這代碼的時候,咱們請求的網址,最好前面加上個‘api’,以下面的紅框中:/api/index.json 這樣子最好了。

很好的是,剛好Vue腳手架裏面有這樣一個轉發的代理功能。經過這個功能,就能夠實現以上構想。

config配置文件下,有個 index.js 腳本,官方給咱們提供了一個 proxyTable{} 的配置項,咱們能夠這樣配置:

這意思是:當咱們請求api的時候,依然映射到本地8080端口,而後訪問任何以api爲開頭的url的時候,作一個路徑替換,代理訪問到 /static/mock 處。

實際這功能 是webpack-dev-sever提供的。

改過配置文件,須要重啓下服務器,重啓後就能夠以下請求數據了:

這裏實際上訪問的就是static/mock/index.json裏的內容了。

優化

若是能夠的話,最好能在局部根組件裏請求一次ajax數據,而後從局部根組件裏把接收到的數據分別傳給各個局部的子組件,而不是每一個局部的子組件都發送一次ajax請求。

城市列表頁開發中想記錄下來的

記box-sizing:border-box的一個應用場景

這裏是這樣寫的css

如今在輸入框裏面輸入文字字符超過輸入框大小時:

這兩部會貼着,不那麼好看。想要給這個輸入框加個padding,留點間隙會更好。

但直接在input下面加行嗎?

頁面:

由於包裹input框的div沒設置width,也就是width是auto。input框的width設置的是100%。

若是直接給input加padding左右一點的話是會撐開input框的寬度的。因此會溢出。

那怎樣解決這個問題呢?

咱們只是想設置一個左右padding值,沒想讓input框長寬變化。因此,咱們在 Input 下面加個:box-sizing: border-box

這樣的話,咱們直接給input設置的寬高就包括了padding、border在內的寬高了。

此時咱們要修改padding的值的話,就只會在這個框內變化 不會撐開框寬高了。

在列表欄用第三方插件 better-scroll

初始開發頁面時,到這步,由於加了比較多字母對應的區域,頁面出現了滾動條的時候:

爲了使用better-scroll庫,咱們僅讓列表區域顯示到剛進頁面時能顯示到的區域就好了,不須要出現滾動條。因此能夠給最外層的包裹整個列表區域的框div.list 加個overflow: hidden就好了。(整個列表頁指下圖中的從當前城市開始到最後,城市選擇和輸入框是其餘子組件寫的了)

接下來具體better-scroll的用法,github上其文檔有說明,各人可根據具體狀況查閱使用。

字母表的邏輯實現思路

點擊事件中,咱們須要查看點擊的內容時,能夠利用點擊事件的事件對象

在Vue的一個點擊事件裏,在methods定義點擊方法時這個方法能夠接收一個參數e,e就是咱們點擊到的那個事件對象。

要拿到咱們點擊到的事件對象的內容 能夠這樣來:e.target.innerText

舉個項目中的例子驗證一下:


好比此時頁面上點擊了 D F J

需求1

當點擊到相應的字母的時候顯示list組件的對應城市的區域。

better-scroll這個第三方插件有個方法能夠實現這個需求,思路是:

監聽所點擊的字母表裏字母的值letter的變化,一旦letter變了,就利用better-scroll的提供的一個接口,以下圖劃線的部分

它會讓better-scroll的滾動區域,自動滾動到某一個元素上。須要給這個方法傳遞咱們滾動到該元素的該元素DOM。

利用這個思路就能夠實現需求1了。

需求2

手指拖動字母表,字母對應的列表跟着聯動展現。

思路:

利用touchstart、touchmove、touchend事件,並給個限制(touchStatus) 只當手指在屏幕移動的時候才執行一些操做。而後用個數組letters來存放字母表的全部字母,這裏的letters大概是['A','B','C'...],並讓頁面v-for這個letters來顯示相應的內容。用數組存放這些字母的緣由也是爲了實現這需求的主要思想:根據下標,找到對應的字母

接下來,先用offsetTop找到字母表中字母A距離包裹它的頂部的高度。下圖紅框。

這裏的74 表明的是紅色方框的高度。

而後獲取移動時手指所在的高度,此高度時針對於客戶端的高度,用clientY。
touchmove事件有個事件對象,事件對象裏有個touches數組,touches[0]裏面就有當前手指的信息,包括clientY屬性。

實時獲取咱們手指的位置。

咱們要獲取距離包裹塊的高度 => 也就是clientY的高度要減去headers區和serach區的高度,這兩個區高度是 79px。

而後算咱們手指移到的字母在數組中的下標 邏輯是 <font color="#dd0000">(touchY - startY)/每一個字母的高度,再把結果向下取個整。</font>

最後,把這個下標在letters數組中對應的字母傳給需求1所在的組件利用需求1的思路就好了。(這裏的傳值涉及到了兄弟組件之間的傳值,此時該頁面比較簡單不建議用vuex,能夠用event bus/找同一父組件作媒介傳值,具體方法百度。)

在我項目中最終邏輯代碼是這樣寫的:

最後作個最佳實踐,用個if,確保 index的值。

性能優化

第一處


handleTouchMove是手指滑動的時候就會執行,而咱們框起來的也就是A字母距離包裹框的高度是固定的,不用每次滑動的都執行這段代碼。

因此此處須要優化,這樣子來:

在data裏初始化startY爲0

而後用生命週期鉤子 updated 去執行給startY賦值的語句

這裏爲何用updated這個鉤子呢?在項目中初次渲染字母表組件alphabet.vue的時候,從它父組件City.vue傳過來的值是一個空對象。當City.vue裏ajax動態獲取數據後,從City再傳到alphabet的值讓數據從初次的空對象發生改變。在數據更新完畢後,就觸發了updated鉤子,此時給startY賦值就是值都有,並且只會賦一次。

第二處:函數節流

經過函數節流 減小handleTouchMove()的執行頻率 (由於咱們手指在滑動的時候 該函數執行頻率很高的)。

怎樣使得函數節流呢?

經過定時器清除定時器來實現。

先在data中初始化timer爲 null,而後這樣來用

這樣子用定時器進行函數節流的話 :

若是已經正在作這件事情的時候,我呢,讓它延遲16ms以後再去執行。假設在這16ms之間你又去作了手指的滾動,那麼它會把上一次你要作的操做給清除掉(clearTimeout),而後從新執行你此次要作的事情 (等於以最終的手指滑動的位置爲準 )。

經過這種函數節流方式,會大大減小該函數的執行次數,從而提升網頁性能。

函數節流的方式,當一個函數執行次數不少想要減小並且減小也沒影響的時候,是頗有必要採用的一種方式。

localStorage

可能用戶會有不小的機率關閉了本地自動存儲的功能,通常咱們使用localStorage的時候 都要使用 try catch 代碼塊,這樣就算用戶關閉本地自動存儲功能,也不會讓整個代碼都不能運行,只是沒了這個localStorage的功能而已。

舉個項目中的例子:

上篇結束,未完待續...

相關文章
相關標籤/搜索