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

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

該說的話,該代表的上篇已經代表了。謝謝上篇評論區一些同窗~ 很鼓勵我,不過下下篇估計沒了,這篇總結完,下下篇可能就是以後學習路的總結記錄啦。vue

有些話仍是要說的

接觸vue不久的朋友應該會有收穫。此項目也纔是萌新作的第二個Vue項目,使用了腳手架工具(vue-cli2.x非3),前輩老手們有時間看的話,有寫得很差的地方還請多多指導!~webpack

項目中Vuex的不那麼低級的用法

由於這只是總結操做/思路,沒一步步講代碼,仍是先給個官網的圖,這樣方便看點:git

前提假設,在腳手架中,咱們跟路由引入全局的方法一致去在全局中引入Vuex。建立一個文件夾store,在文件夾下建立個index.js腳本。在store/index.js裏面寫Vuex的一些用法邏輯,而後在入口函數main.js裏引入就好了。以下:github

先忽略馬賽克...web

在入口函數main.js中引入:ajax

此時index.js裏面的邏輯vue-cli

拆分

以此項目中爲例,隨着項目的開發,index.js裏的邏輯會愈來愈複雜,因此選擇拆分。npm

因此,咱們創建兩個腳本(state.js、mutations.js)來分別存儲這兩段代碼。後端

而後在index.js中引入:

這樣拆分完成,簡潔很多。

mapState輔助函數

在項目中,以下圖用法去取得state裏面city的數據,是否是顯稍長了點?

Vuex爲咱們提供了一個方便的API -> mapState

這樣用:

mapState是指,我把State區域裏面的公有屬性值映射到這個計算屬性裏。

在這裏是:把state裏city這個公有屬性的值映射到這裏的計算屬性city裏。

這樣子的話,就能夠把

變成能夠直接調用這個計算屬性:

...mapState({}/[])這裏面能夠是數組也能夠是對象。是數組的話,那咱們就等於直接給計算屬性取名city了,和公有屬性的名稱同樣。

是對象的話,咱們就能夠給計算屬性自定義取名。

舉個...mapState(對象)的例子:

在當前城市這裏也能夠改:

這裏就是傳對象給mapState,等於把公有屬性city的值映射到計算屬性currentCity裏。

此時就能夠這樣用:

這樣子就不用寫的那麼複雜了。

mapMutations輔助函數

利用Vuex提供的這個API能夠簡化下列代碼:

這樣用:

mutations裏面是有changeC2()這個函數的(這個命名就....僅當測試,輕噴)。咱們想在組件中調用mutations裏的這個函數去改變公有數據區域state裏的值,運用mapMutations能夠這樣簡潔地在組件中調用。

這什麼意思呢?

mutations裏有個叫作changeC2這個方法,這裏在該組件的methods中是把這個mutations裏的changeC2方法映射到了該組件中methods的changeC2方法裏。

...mapMutations()參數也是可接收[]/{}的。

仍是用...mapMutations(對象寫法)好理解一點,以下,作個測試:

(亂入的小姐姐~)

這樣子寫也是能夠的。也更容易理解這裏的映射。

Getter、Module

Getter和Module該項目中都沒有用到。

Getter

假如咱們想根據state的值,經過一些計算獲得新的值的話,就能夠用getter來提供新的數據,避免數據冗餘。它的定義也和computed同樣。

getter能夠認爲是store的計算屬性。就像計算屬性同樣,getter 的返回值會根據它的依賴被緩存起來,且只有當它的依賴值發生了改變纔會被從新計算。

Getter 接受 state 做爲其第一個參數,也能夠接收其餘 getter 做爲第二個參數。能夠屬性訪問(store.getters),能夠經過方法訪問,也有 mapGetters輔助函數(該輔助函數主要也是映射關係,將store中的getter映射到局部組件的計算屬性中)。官方文檔給的例子也比較好理解,能夠自行看文檔。

Module

Module的話,看得勉強理解,Vuex容許咱們將store分割成模塊(module)。每一個模塊擁有本身的state、mutation、action、getter、甚至是嵌套子模塊。

當應用變得很是複雜時,可使用Module避免store對象變得至關臃腫。

我以爲Module具體的應用要在複雜項目中親自練手過才能熟練,目前不敢輕易下手記錄,暫且記一筆。

使用keep-alive優化性能

咱們能夠在 開發者工具 network 的xhr 中看到

每次咱們路由切換的時候(從Home組件頁面跳轉到City組件頁面或反之的時候)都要發送ajax請求數據。

這樣子就重複請求ajax數據了,由於每次路由切換到一個組件的時候,都要從新執行該組件鉤子函數,若是該組件有在mounted鉤子裏請求ajax的話,就每次路由切換都要執行了。這樣性能很差。

此時就能夠用vue內置的 keep-alive標籤來優化。

在全局根組件App.vue中

表明的是顯示當前路由的組件,而在這個外面加個 vue 內置的 keep-alive標籤後,就能夠實現這樣一個功能:

個人路由的內容被加載過一次以後,個人路由中的內容就都放到內存之中,下一次再進這個路由的內容的時候,就只須要從內存裏把之前的內容拿出來就能夠了。

此時,無論切換多少次路由,都只有兩次ajax數據請求了。

由於使用了keep-alive標籤,致使有了新的生命週期函數activated(keep-alive組件激活時調用)、deactivated(keep-alive 組件停用時調用)。

以後的路由切換再也不請求ajax數據是由於組件內容是從內存取了不會再從新建立了,對應的mounted鉤子函數不會再執行了。

但每次切換、頁面從新顯示的時候,activated鉤子會執行。

此時能夠利用這個鉤子實現一個需求:

當在列表頁選擇點擊了哪一個城市後,路由切換回到首頁時,首頁顯示的數據是對應着該城市的數據(意味着ajax只請求該城市對應的Home組件頁面的數據),而後若是在列表頁,選擇了與本來在Home頁相同的城市的話,就不發送ajax請求新數據。

以前,發ajax請求的時候,是直接這樣子發:

實際上,在發送ajax請求的時候,應該帶一個參數的。帶的這個參數應該是 Vuex 中公有的這個數據。也就是當點擊哪一個城市的時候,這個參數就是對應哪一個城市的名稱。

怎麼在請求中帶參數呢?

在請求的鏈接後面 加上 ?=參數數據

如:

在網頁上試一試,發送的參數就在下面

實現需求的思路是:

在每一次頁面從新顯示的時候(activated鉤子函數觸發)咱們判斷此時頁面上的城市是否和上一次顯示的城市相同 若是不相同 就發送ajax請求

而後咱們設置個空字符串 lastCity (當作一箇中間緩存值用於判斷)

緊接着,當頁面掛載完畢的時候,咱們給它賦予當前頁面的城市數據。

而後在頁面更新的時候,判斷上一次的 this.lastCity 的值 是否等於 更新後的 this.city 的值。若是不等於的話,就發送新的ajax請求,請求相應city的數據,若是等於的話就不發送。

此時,經過keep-alive新增的生命週期鉤子函數以及lastCity這個緩存值就實現了咱們要的功能了。

詳情頁想記錄下來的東西

實現畫廊組件功能的主要思路

先看個gif說明此功能啥樣:

就這個玩意兒。這個就是畫廊。上面有輪播,下面有頁碼。

由於這不只僅只有一個頁面會用到,可能之後不少頁面都會用到,因此 寫個全局公用的組件Gallary.vue。

須要在詳情頁的一個組件 Banner.vue 裏面去使用這個公共組件

gallary用fixed佔滿全屏。

利用flex佈局,讓這個以下wrapper區域垂直居中

而後使用 Vue-awosome-swiper第三方插件,先放入兩張圖

而後給那個.wrapper定義個寬高100%。按照以下這種寫法的話width先有個100%的寬度了而後height也100%的意思是針對於這個width的寬度來講的,因此這裏定義了這個100%的height的意思是這個height與width的寬度相等 意思是一個正方形。

此時頁面:

咱們讓圖片按比例自適應這個正方形,再把wrapper下的背景顏色去掉,此時兩張圖片能夠正常顯示輪播了:

而後加頁碼,其實這個頁碼就是該插件的按鈕區和配置參數一塊兒控制的。先加上按鈕區代碼:

vue-awesome-swiper這個插件是基於swiper實現的,這裏面的配置參數好比 pagination 能夠去 swiper 官網找的。

咱們去官網找找看能不能找到配置咱們頁碼需求的參數(固然是能找到的,否則我還寫個啥...):

因而可知,這個頁面的翻頁樣式就是對應這個paginnation中的paginationType 中的 fraction。

如今來配置參數,首先在swiper上加上 :options="swiperOption"。

而後在data裏配置。先把按鈕區配置出來:

再把paginationType ‘fraction’ 分式 給配置出來

如今就有了,但在小小的地方,審查元素才能夠看見

本來框架的樣式,經過審查元素找出這裏是絕對定位。

那麼咱們這樣改bottom -1rem就好了?

那確定是不行的...

這裏有個坑,當感受代碼沒寫錯,頁面卻沒達到預期的時候,就是再次審查元素的時候了...審查元素髮現這個插件組件有個swiper-container裏還定義了個overflow: hidden。

因此咱們在畫廊組件裏穿透做用域來改掉這個樣式就行

畫廊邏輯部分很簡單就跳過不記錄了,不過有個坑仍是值得提一下。

在畫廊自身的組件gallary.vue裏測試功能的時候都好好的,可是gallary這個公有組件是要在詳情頁的Banner.vue組件中引入的。

那麼問題就來了,當咱們在Banner組件對應的頁面一會兒點進去gallary組件對應的頁面的時候,輪播插件會出現一個計算寬度高度的問題。以下gif圖這樣:

要解決這個問題,須要在gallary的輪播插件配置參數中加上這兩個配置參數

加上這兩個參數的意思是:

我這個swiper插件,只要監聽到我這個元素,或者父級元素變化的時候(這個監聽的就是swiper和swiper的父級元素),這個插件會自動地自動刷新一次,從新計算寬高。

經過此次自我刷新,就能夠解決輪播插件的這個計算寬度高度的問題。(這些配置參數在swiper官網均可以查到怎樣用的)

實現header區塊漸隱漸現的效果

看個gif。

僅提這段,當手指往下滑的時候,逐漸顯示清晰以後一直清晰的div景點詳情框邏輯。

這個逐漸顯示清晰的這塊是用個div框來fixed定位寫的。

邏輯

一開始v-show不顯示這個div框而且讓該div框的opacity爲0,在activated鉤子函數中檢測全局scroll(window.onscroll)事件(即檢測滾動條的狀態,滾動條一旦動了就觸發scroll事件),當觸發scroll事件時,執行一個方法,此方法裏面寫邏輯。寫的邏輯是:當滾動條往下滑動60px外時讓這個div框的v-show參數爲true而且經過公式 let opacity = document.documentElement.scrollTop / 140 來讓該div框隨着越往下滑動清晰度越高,而後在這條語句下面限制opacity透明度值爲1:opacity = opacity > 1 ? 1 : opacity

顯而易見:document.documentElement.scrollTop的意思是獲取當前頁面的滾動條縱座標位置。

這樣功能實現了,但還有個很重要的坑。對全局事件的解綁。

對全局事件的解綁

在header區塊邏輯中,咱們在activated鉤子中定義了個全局scroll事件。

由於這個是全局事件,因此咱們在其餘組件中也能夠監測到。這樣很容易引起一系列嚴重的隱藏的bug。

因此咱們應該在detail下header.vue組件中對該組件解綁:

對應keep-alive引用而可使用的鉤子還有一個deactivated鉤子。

該鉤子在頁面即將被替換成新的頁面的時候觸發。

因此這裏咱們利用deactivated鉤子removeEventListener函數來解綁全局事件。

組件中name屬性的三個做用

一、作遞歸組件的時候會用到

舉個例子,list組件的name: 'DetailList'。在list組件模板中想要使用遞歸組件調用自身時,就要根據name的值來用做標籤(detail-list)調用。以下:

二、對某個頁面取消keep-alive的緩存的時候會用到

假設有個Detail.vue組件,其name: ' Detail'。當想要keep-alive全局組件時,Detail.vue組件對應的頁面,路由從新切換到這個頁面不用去內存中取緩存值,能夠利用Detail組件的name的值以下使用:

這樣等因而除了Detail.vue組件,其餘組件均可以擁有設置keep-alive後的功能。

三、vue-devtools調試工具

如上圖紅框裏的組件名稱,這裏的名稱就取決於設置的組件的name屬性的值。

動態路由中ajax動態獲取各個路由目錄對應的值

舉項目中例子說明,注意下圖紅框中的值

此時咱們應該獲取的是,動態路由中 id爲0002的參數的數據。

這樣設置後,其實動態路由中,會把對應的參數存在 這個變量id裏。

每次請求,但願把這個id帶給後端,就能夠這樣寫:

寫法一

如今能夠在network的XHR裏看見咱們發送給後端的請求中附帶了 id

寫法二

前面只寫接口名 後面這樣子寫(咱們把參數放到params去了):

其實還有問題,這地方我想一步一步來總結

設置的動態路由,只是動態加了個id參數並不能自動讓頁面也跟着動態顯示數據,動態顯示數據還得靠ajax請求數據。

而目前這個組件是在mounted鉤子中執行ajax請求的,而且該組件有keep-alive的做用影響着。這樣當路由跳轉到id爲0003/0004...頁面的時候,組件也只會從內存中取出第一次進入該組件某個id的頁面。並不能根據id對應顯示頁面。

怎樣經過ajax請求而動態顯示數據呢?有兩種方法,兩種方法上面都提到過。

  • 第一種 在列表頁選擇某個城市,路由自動跳轉回首頁後,首頁須要顯示的是該城市對應的數據這裏記錄過。(提示一下:利用activated鉤子,判斷參數id是否等於以前的id,若是不等則從新執行ajax請求。)

  • 第二種 組件中name屬性的三個做用中的第二個做用已經說出瞭解決方案。

這兩種方式留給讀者自行思考,想不通的能夠參考下我github該倉庫裏的代碼。src/pages/detail/Detail.vue

路由滾動行爲

來看個gif

這就是路由跳轉頁面會帶來的影響。會把當前頁面(Home.vue)的屏幕的顯示的寬高 帶到 咱們跳轉到的頁面(Detail.vue)上去。形成如上gif所示現象。

這樣來解決。

這個在官方文檔中稱爲 路由的滾動行爲。

咱們如今是想讓每次路由切換進入到下一個頁面的時候滾動在頂部顯示。 繼續看文檔。

把這段代碼複製到路由配置項中:

這樣就實現咱們預期的需求。

配置打包

先後端聯調

通常等後端數據寫好後,咱們就再也不使用本身前端模擬的數據,而是去使用後端給過來的數據來調試。

若是要訪問服務器上的數據的話,要在配置文件config/index.js下的proxyTable裏把target改成服務器的地址(能夠寫內網的IP地址 或 外網的域名都行)。而後改pathRewrite的話,就見實際狀況數據存放在服務器的哪一個文件夾下了。

真機測試

這裏的前端的項目是經過 webpack-dev-server 啓動的,默認不容許經過ip來訪問內部服務器。因此咱們須要把默認的配置項作修改。

想讓這個 webpack-dev-sever 可以被ip訪問的話,須要這樣配置下:

(貌似漏點了... 其實也不要緊....)

而後這裏真機測試的時候,有時候就會遇到一些在PC上開發時發現不了的bug以及要考慮兼容性。這個就要各人根據實際狀況來改了。

打包上線

vue-cli 2.x中,就能夠在項目目錄下執行指令 npm run build,此時Vue的腳手架工具會幫咱們自動地對src目錄下源代碼進行打包編譯生成一個能被瀏覽器運行的代碼,同時這個代碼也是壓縮事後的代碼。

打包完成後會生成一個dist文件夾,給到後端開發人員,或者直接把static文件夾裏的內容扔到後端服務器根目錄上就OK了。這只是基本的操做,想要改變訪問路徑或怎樣的操做,就各位小夥伴本身去找了,有心自會找到~

結語

這篇文章僅是在這個項目中對於我我的而言以爲能夠總結記錄下來的,更具體更詳細的知識和流程,感興趣不妨去imooc支持一下DellLee老師的這門課程~

有部分地方代碼量太多不方便貼出來,想參考代碼學習的能夠進我Github

但願也能幫到大家~

相關文章
相關標籤/搜索