Vue—去哪兒筆記

狸xun尋發表於2018-05-29

專案程式碼

一.專案環境準備

Vue專案執行在NodeJ環境中,npm為NodeJs的包管理工具,命令列 node -v ,npm -v 中檢視系統是否已經安裝Node環境。如果還沒安裝環境,就前往 Node官網下載吧。
接著安裝 vue-cli 腳手架工具,vue-cli能夠幫助我們快速構建Vue專案。安裝腳手架:npm install --global vue-cli,建立vue專案: vue init webpack my-project,npm install 執行專案:   npm run dev。

二.專案程式碼結構介紹

下面來介紹下vue專案目錄

README.md  專案說明檔案

package.json  專案開發需要的第三方依賴包

LICENSE 開源協議的說明

index.html  專案預設首頁檔案

.prostcssrc.js 

.gitignore 

.eslintrc.js  配置程式碼規範

.eslintignore  檔案不受程式碼規範限制

.editorconfig  編輯器語法

.bablelrc 通過bable語法解析,編譯能夠執行的程式碼

 static  靜態資源  存放靜態圖片 mock模擬資料

 src 整個專案的原始碼

       main.js專案入口檔案

       App.vue專案原始根元件

       router/index.js 整個專案的路由配置

       components專案需要的元件

       assets 專案需要的圖片

node_modules 專案依賴的第三方node包

config 專案配置檔案

       index.js基礎配置資訊

       dev.env.js 開發環境配置資訊

       prod.env.js 線上生產環境配置資訊

build  專案打包webpack配置內容

三. 單檔案元件與Vue中的路由

單檔案元件.vue 是由元件模板<template></template>,元件邏輯結構<script></script>,元件樣式<style></style> 三部分構成。                                                

路由就是根據網址的不同,返回不同的內容給使用者。路由配置一般都在router目錄下的index.js下啦。說到路由,不妨提下Vue中的頁面路由:原生中可以通過<a>標籤和 js的href屬性進行頁面的跳轉,Vue 同樣也有兩種方法進行路由,分別是:<router-link to=' ' > 和 this.$router.push('/') 。

路由後拖動,多個介面之間會互相影響。在路由配置頁index.js新增以下程式碼即可:

scrollBehavior (to, from, savedPosition) {
      return { x: 0, y: 0 }
    }複製程式碼

四.多頁面應用和單頁面應用的區別

Vue是單頁面應用,那單頁面應用和多頁面運用又有什麼區別呢?

單頁面應用(SinglePage Web Application,SPA)

頁面跳轉 ——> JS渲染

優點:頁面切換快 (js會感知url的變化,通過js感知到url的變化,js 動態地把當前頁面的內容清楚掉,再把下一個頁面的內容掛載到頁面上。這時候,路由不是後端來做,而是前端來做。)

缺點:首屏時間稍慢 (首屏展示出來需要請求一次html和傳送一個JS的請求,兩個請求都回來了,首屏才會被展示出來),SEO差。

vue中還提供了伺服器端等技術,通過這些技術,可以完美地解決單頁面應用的這些問題。

多頁面應用(MultiPage Application,MPA)

 指的是頁面跳轉—— >返回HTML

 優點:首屏時間快,SEO效果好(搜素引擎優化效果好,搜尋引擎在做網頁排名的時候需要知道網頁的內容,根據網頁內容給予權重從而進行排名。搜尋引擎可以識別html中的內容的)。

 缺點:頁面切換慢 (每次跳轉頁面的時候都需要傳送http請求,網路比較慢的時候,在頁面來回跳轉的時候,會出現明顯的卡頓情況)。

五.專案程式碼初始化

在正式編寫程式碼之前,我們先進行一些程式碼的初始化。

 a.在預設首頁檔案index.html 完善<meta>標籤的viewport配置

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

這樣的話,要求使用者對於移動裝置的放大縮小都是無效的,並且頁面的比例始終是1:1。

b. 在專案入口檔案main.js中引入重置頁面樣式表reset.css

import './assets/styles/reset.css'
複製程式碼

c.引入一畫素邊框檔案  

  (1畫素邊框問題)有的手機螢幕解析度比較高,為2倍屏或者3倍屏。如果在頁面上寫     border:1px solid  black;這時候寫的是1px,指的是css畫素。但是在2倍屏上1px css畫素對應的不是1個物理高度的畫素,而是兩個物理高度的畫素。

d. 安裝第三方依賴庫fastclick

    (移動端有300毫秒點選延遲的問題) 移動端開發中,在某些機型上,某些瀏覽器上,當使用click 點選事件的時候,click 事件會延遲300 毫秒後才執行。

 安裝fastclick 庫  (--save表示無論在開發環境或者生產環境中都使用 fastclick)

npm install fastclick --save複製程式碼

引入

import fastClick from 'fastclick'
複製程式碼

使用

fastClick.attach(document.body)
複製程式碼

e. iconfont管理

去iconfont官網註冊登入建立自己的專案,選擇你要的圖示加到購物車,都選擇完後,將購物車的圖示都加到專案中,然後下載到本地,選擇字型檔案和iconfont.css新增到Vue專案中,並在main.js檔案中import。然後就可以使用啦,類名為“iconfont" ,&#xe632;為圖示對應的進位制程式碼,官網裡可以檢視。(不要忘記修改iconfont.css裡的字型檔案的路徑)

<span class="iconfont">&#xe632;</span>
複製程式碼

Vue—去哪兒筆記e.專案中使用stylus

安裝依賴包  npm install stylus --save

                   npm install stylus-loader --save

<style lang="stylus" scoped>

使用stylus ,scoped 區域性化樣式 表示樣式只對當前元件起作用,不影響其他元件。

專案中我們使用rem做自適應佈局,rem是根據html的font-size大小來變化,html font-size  = 50px =1rem (為方便計算,html font-size可以根據自己設定)

f.程式碼優化,定義樣式變數

新建一個varible.styl 檔案,定義樣式變數

$bgColor = #00bcd4
複製程式碼

在元件樣式中引入檔案(<style>樣式中引入import前要加@)

@import '../../../../assets/styles/varibles.styl'複製程式碼

此時檔案路徑很長,容易搞錯,@代表src目錄 ,所以我們可以將路徑修改成:(記得在@前加~)

@import '~@/assets/styles/varibles.styl'
複製程式碼

在stylus中使用

background: $bgColor複製程式碼

另外,有的目錄我們經常使用到,比如stylus目錄,那有什麼辦法給目錄起個別名呢?讓我們更方便地訪問。(就好像src目錄的別名是@ 一樣)

解決辦法:開啟build目錄下的 webpack.base.conf.js 檔案,找到 alias 別名項

'@': resolve('src'),
複製程式碼

根據src 的配置,可以配置你想要的路徑的別名,如

'styles': resolve('src/assets/styles'),
複製程式碼

那麼我們就可以更改上面複雜的路徑了

  @import '~styles/varibles.styl'
複製程式碼

(提示:當我更改了webpack配置項的時候,記得重啟伺服器,ctr c    npm run start)

六.碼雲的運用

我的專案放在碼雲上面啦,當然更推薦大家使用github~

首先在碼雲上建立專案,具體的這裡就不多說啦。然後 git clone adress 下載碼雲倉庫程式碼到本地(SSH程式碼協議進行克隆)。

建立git分支。在真正的企業級別的開發中,我們每開發一個新的功能,都要建立一個git的分支,在分支上進行程式碼的開發。當程式碼開發完成之後,把分支的程式碼合併到master主分支上。Vue—去哪兒筆記


然後在git bansh終端執行 git pull ,就會將我們建立的 index-swiper 分支 拉到本地來。

在執行 git checkout index-swiper  ,這時候本地所在的分支就切換到 index-swiper 分支了。

將程式碼儲存到本地倉庫,並提交到線上倉庫。

git add .     git commit -m ' '   git push

這個時候本地的index-swiper分支就提交到線上index-swiper分支了。

然後再將index-swiper分支上的內容合併到master分支上。

git checkout master //先切換到master分支上

git merge origin/index-swiper //然後把線上的index-swiper分支上新增的內容合併到本地

的 master分支上。

git push //將本地的master分支提交到線上。

master分支放的上整個專案所有功能的最新程式碼。index-swiper放的是開發的具體功能的開發完成時的程式碼。所以在實際企業級新專案開發中,我們會自己開發一個分支,測試沒有問題後,再把這個分支的程式碼合併到主分支上。

七.AJAX獲取資料

 axios第三方模組,可以實現跨平臺的資料請求。axios十分強大,在伺服器端axios可以幫助你傳送xhr的請求;在node伺服器上,可以幫助你傳送http請求。

安裝axios

npm install axios --save複製程式碼

引入

import axios from 'axios'
複製程式碼

使用mock模擬資料

 axios.get('/static/mock/index.json')

我們現在用的都是本地模擬介面的地址,加入程式碼要上線,在上線之前,需要把這塊地址重新替換成  axios.get('/api/index.json') 這種格式,上線之前去改程式碼,是有風險的。不建議大家這麼做。那怎麼才能解決這個問題呢?我們想,在開發環境中,我們依然這麼寫我們的路徑 axios.get('/api/index.json'),如果有一個轉發機制,可任意幫助我們把 對api下所有json檔案的請求 轉發到本地的mock資料夾下。vue提供了proxy的代理功能,就可以實現我們的構想啦。

開啟config目錄下,在index.js檔案,在開發環境裡,官方提供了 proxyTable 這個配置項,在這裡做些配置,就可以我們剛才的想法。

proxyTable: {
      '/api' : {
        target: 'http://localhost:8081',
        pathRewrite: {
            '^/api': '/static/mock'
        }
      }
    }
複製程式碼

當我們去請求api這個目錄的時候,我們希望它把請求轉發到當前這臺伺服器的埠號上,然後對路徑進行替換。 如何替換? 一旦你請求的地址是以 api 開頭的,就替換請求到本地的static路徑下的mock這個資料夾下。當你去訪問api下面的index.json的時候,在開發環境中,vue-cli腳手架工具會自動幫助你把api 替換成/static/mock。

(提示:當我更改了webpack配置項的時候,記得重啟伺服器,ctr c npm run start)

八.輪播藉助第三方的輪播外掛 vue-awesome-swiper

安裝(npm)

npm install vue-awesome-swiper@2.6.7 --save複製程式碼

使用(全域性引入)

import VueAwesomeSwiper from 'vue-awesome-swiper'複製程式碼
import 'swiper/dist/css/swiper.css'複製程式碼
Vue.use(VueAwesomeSwiper)複製程式碼

在template中使用可以檢視官網文件。

<!-- The ref attr used to find the swiper instance -->
<template>
  <swiper :options="swiperOption" ref="mySwiper" @someSwiperEvent="callback">
    <!-- slides -->
    <swiper-slide>I'm Slide 1</swiper-slide>
    <swiper-slide>I'm Slide 2</swiper-slide>
    <swiper-slide>I'm Slide 3</swiper-slide>
    <swiper-slide>I'm Slide 4</swiper-slide>
    <swiper-slide>I'm Slide 5</swiper-slide>
    <swiper-slide>I'm Slide 6</swiper-slide>
    <swiper-slide>I'm Slide 7</swiper-slide>
    <!-- Optional controls -->
    <div class="swiper-pagination"  slot="pagination"></div>
    <div class="swiper-button-prev" slot="button-prev"></div>
    <div class="swiper-button-next" slot="button-next"></div>
    <div class="swiper-scrollbar"   slot="scrollbar"></div>
  </swiper>
</template>

<script>
  export default {
    name: 'carrousel',
    data() {
      return {
        swiperOption: {
          // some swiper options/callbacks
          // 所有的引數同 swiper 官方 api 引數
          // ...
        }
      }
    },
    computed: {
      swiper() {
        return this.$refs.mySwiper.swiper
      }
    },
    mounted() {
      // current swiper instance
      // 然後你就可以使用當前上下文內的swiper物件去做你想做的事了
      console.log('this is current swiper instance object', this.swiper)
      this.swiper.slideTo(3, 1000, false)
    }
  }
</script>複製程式碼

Vue—去哪兒筆記

當輪播圖ajax資料獲取完成後,swiperList變成真正的資料項。再傳給HomeSwiper元件的時候,元件才獲取到資料,然後重新渲染出來。因為swiper的初始化建立是根據空陣列建立的,所以預設顯示的是所有輪播圖的最後一項。

解決辦法:swiper的初次建立讓完整的資料來建立,而不是由空陣列建立。只需 新增v-if="list.length" ,當傳遞過來的list是空陣列的時候,v-if為false,所以swiper不會被建立。只有真正的資料過來的時候,swiper才會被建立。

其實這樣寫是不優雅,模板程式碼儘量不要寫邏輯。所以可以新增一個計算屬性

computed: {
    showSwiper () {
      return this.list.length
    }
  }
複製程式碼

//一些css需要注意的點

防止輪播圖載入過程中下方內容的抖動,可以給<swiper>包裹一層div,並且設定樣式

寬高佔比

.wrapper
    overflow: hidden
    width: 100%
    height: 0
    padding-bottom: 31.25%
    background: #eee
複製程式碼

樣式穿透,wrapper樣式下的所有swiper-pagination-bullet-active樣式 不受 scoped 限制。

.wrapper >>> .swiper-pagination-bullet-active
    background: red !important複製程式碼

當文字很多,空間又不足,顯示省略號

ellipsis()
  overflow: hidden
  white-space: nowrap
  text-overflow: ellipsis複製程式碼

一畫素邊框顏色不明顯

.border-topbottom
    &:before
      border-color: #ccc
    &:after
      border-color: #ccc
複製程式碼

.border-topbottom 這個類的 bofore 和 after 偽元素的border-color 都設定為 #ccc,而通過控制這個顏色,就可以控制頁面上一畫素邊框的顏色。

漸變

background-image: linear-gradient(top, rgba(0,0,0,0), rgba(0,0,0,8))複製程式碼

九.Better-scroll的使用

better-scroll 安裝

npm install better-scroll --save複製程式碼

想要使用 better-scroll 元素需要符合如下dom結構

<div class="wrapper">
  <ul class="content">
    <li>...</li>
    <li>...</li>
    ...
  </ul>
  <!-- you can put some other DOMs here, it won't affect the scrolling -->
</div>複製程式碼

使用

import BScroll from 'better-scroll'
const wrapper = document.querySelector('.wrapper')
const scroll = new BScroll(wrapper)複製程式碼

十.兄弟元件聯動

兄弟元件是非父子元件,非父子元件傳值可以使用 bus匯流排 形式進行傳值。

但是我們這個兄弟元件比較簡單,當我們處理兄弟元件的時候,可以讓 Alphabet元件的資料傳遞給City元件,City元件再轉發給List元件。

Vue—去哪兒筆記

點選的聯動(點選城市列表頁的右側字母表,左側的列表會自動地滾動到頁面的顯示區域之中)點選觸發事件右側字母子元件,獲取字母(e.target.innerText),並通過$emit方法觸發change事件 將字元傳給City父元件,父元件獲取到字母后,又通過屬性傳值給城市列表子元件,城市列表子元件通過監聽字母地變化,獲取字母的dom節點,通過better-scroll的scrollToElement實現自動地滾動。

滾動的聯動(滑動城市列表頁的右側字母表,左側的列表會自動地滾動到頁面的顯示區域之中) 定義一個標識位,手指觸控的時候標識位位true,結束滑動的時候標識位為false。只有再標識位為true的情況下,才去做move事件的處理。我們得知道往下滑動的時候,你現在所在的位置是第幾個字母。思路是這樣的:首先獲得首字母A距離頂部的高度,再獲得滑動時當前手指距離頂部的高度,做差值就能算出當前手指位置與首字母A的距離,再除以每個字母的高度,就能知道當前滑動的是第幾個字母了。然後去取對應的字母,觸發change事件給外部,剩餘同上。

十一.列表切換效能優化

當我們手指在字母表上滑動的時候,就會觸發handleTouchMove()事件,但是這樣寫效能會比較差。

handleTouchMove (e) {
      if(this.touchStatus) {
         const startY = this.$refs['A'][0].offsetTop
         const touchY = e.touches[0].clientY - 79
         const index = Math.floor((touchY - startY) /20)
         if(index >= 0 && index < this.letters.length ) { 
         this.$emit('change', this.letters[index])
        }
     }
 }
複製程式碼

首先,A的offsetTop值是固定的,而我們需要每次執行這個方法的時候(滑動字母),都會去運算一次 A到頂部的高度。為了提高效能,我們可以用updated 生命週期鉤子,當頁面資料被更新的時候,同時頁面完成了自己的渲染之後,updated這個鉤子就會執行。

 updated () {
     this.startY = this.$refs['A'][0].offsetTop
  }
複製程式碼

當初次渲染字母元件的時候,是用空物件cities渲染的,當ajax獲取到資料之後,cities的值才發生變化,字母元件才被渲染出來。當網字母元件傳的資料發生變化的時候,字母元件就會重新渲染。當字母元件重新渲染之後,updated這個生命週期鉤子就會被執行,這個時候字母元件就展示了字母的所有內容,這個時候去獲取A到頂部的高度。

函式節流

當我們滑鼠或者手指在字母表來回移動的時候,touchmove執行的頻率是非常高的。我們可以通過節流限制函式執行的頻率。

 handleTouchMove (e) {
      if(this.touchStatus) {
        if(this.timer) {
         clearTimeout(this.timer)
        }
       this.timer = setTimeout(() => {
         const touchY = e.touches[0].clientY - 79
         const index = Math.floor((touchY - this.startY) /20)
         if(index >= 0 && index < this.letters.length ) { 
         this.$emit('change', this.letters[index])
       }
      }, 16)
    }
  }
複製程式碼

如果你已經正在滑動,讓其延遲16毫秒再去執行,假設在16毫秒之間,又做了手指的滾動,那麼就會把上一次要做的操作清除掉,重新執行這次要執行的事情。

十二.使用Vuex實現資料共享(首頁和城市選擇頁的資料共享)

Home.vue與City.vue 沒有公用的父級元件,這樣的話城市頁面和首頁進行資料傳遞就沒辦法通過一個父級的元件進行資料的中轉。那該如何進行這兩個頁面的資料通訊呢?這裡我們可以使用BUS匯流排的方法,但是依然比較麻煩。Vue的官方提供了一種工具,叫做vuex。這是官方推薦的一個資料框架。在vue的大型專案開發之中,vue只能承擔檢視層的主要內容,當我們涉及到大量資料之間傳遞的·時候,往往需要資料框架進行輔助。

如何使用vuex 資料層框架

vuex

Vuex指的是整個專案虛線部分的內容。那Vuex是什麼呢,當我們的專案中各個頁面或者多個元件之間進行復雜的資料傳值很困難的時候,如果能夠把公用的資料放到一個公共的儲存空間進行儲存,然後某一個元件改變了公共的資料,其他元件就能感知到。Vuex的設計理念就是這樣的。

上圖中,Vuex虛線部分就是一個公用資料儲存區域,可以理解為是一個倉庫。倉庫中有一個State區域,所有的公用資料都存放在State之中,那元件如果想用一個公用的資料,直接去呼叫State 就可以了。有的時候我們想改變State裡的資料,(不能讓元件直接去改變資料)流程是這樣的:如果有非同步操作,就把非同步操作放在Actions裡,或者一些比較複雜的批量的同步操作也可以放到Actions裡。元件先去呼叫Actions,Actions緊接著去呼叫Mutations,Mutations裡面放的是一個一個同步地對State的修改。當然這也不是絕對的,有的時候可以讓元件直接去呼叫Mutations去修改State裡面的資料。需要注意的是,當元件呼叫Actions的時候,呼叫的是一個Dispatch()方法來操作Actions,Actions或者元件呼叫Mutations的時候需要用到Commit()方法。

安裝vuex

npm install vuex --save複製程式碼

直接在main.js中引入vuex使用vuex,這樣做其實不太好,vuex要做的資料夾其實是比較複雜的。所以,單獨在src目錄下建立一個store資料夾,然後再store資料夾建立一個index.js的檔案。

vuex是一個外掛,vue裡面使用外掛都是通過Vue.use( )使用的。

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store ({
	state: {
		city: '北京'
	}
})複製程式碼

然後在入口檔案main.js中引用

import store from './store'
複製程式碼

new Vue({
  el: '#app',
  router,
  store,
  components: { App },
  template: '<App/>'
})
複製程式碼

這樣就可以在各個元件中使用啦

<div>
   {{this.$store.state.city}}
</div>複製程式碼

Vue—去哪兒筆記

現在我們想通過點選“熱門城市”來改變“當前城市”,就是公用城市也要跟著變化,那該怎麼做呢?(改變state)

首先需要呼叫Actions然後再去呼叫Mutations。

在list元件中點選熱門城市改變city的時候,通過dispatch()方法呼叫 actions,傳遞兩個引數,分別是'changeCity' 這個actions和 要改變的city

handleCityClick(city) {
      this.$store.dispatch('changeCity',city)
    }
複製程式碼

在store中建立一個actions物件,接受到dispatch過來的一個‘changeCity’方法,接受兩個引數分別是上寫文ctx和傳遞過來的資料city。actions要通過commit來呼叫mutations,mutations來改變資料。

export default new Vuex.Store ({
	state: {
		city: '北京'
	},
	actions: {
		changeCity (ctx,city) {
			ctx.commit('changeCity',city)
		}
	},
	mutations: {
		changeCity (state,city) {
          state.city = city
		}

	}
})複製程式碼

以上步驟改變State的過程裡並沒有任何的非同步操作,也不是批量操作,所以這個時候元件沒必要去呼叫Actions ,元件可以直接去呼叫Mutations。

 handleCityClick(city) {
      this.$store.commit('changeCity',city)
    }
複製程式碼

export default new Vuex.Store ({
	state: {
		city: '北京'
	},
	mutations: {
		changeCity (state,city) {
          state.city = city
		}

	}
})複製程式碼

十三.Vuex的高階使用及localStorage

html5中引入了一個新的API localStorage ,可以幫助我們實現cookie的功能,做到本地儲存。在這裡我們用localStorage完成城市儲存的功能。

需要注意的是:當你使用localStorage,建議就在外層包裹一個try catch。因為在某些瀏覽器,如果使用者關閉了本地儲存這樣的功能,或者選擇隱身模式,你使用localStorge有可能會導致瀏覽器直接丟擲異常,導致程式碼無法執行。

 try{
       localStorage.city = city
    } catch (e) {}
複製程式碼

let defaultCity = '上海'
try {
     if(localStorage.city) { 
     defaultCity = localStorage.city
	}
} catch (e) {}
複製程式碼

這樣寫程式碼,就比較規範了。

此時store下的index.js變得複雜起來了。為了易讀性和可維護性,我們可以對程式碼進行拆分。怎麼拆分這裡就不多說啦。


Vue—去哪兒筆記Vue—去哪兒筆記

有的時候因為城市名的長度,首頁header元件樣式會被破壞。

.header-right
      width: 1.24rem
      float: right
      text-align: center
      color: #fff
      .arrow-icon
        margin-left: -.04rem
        font-size: .24rem複製程式碼

這裡我們設定一個左右的padding,將width改為min-width就可以啦

.header-right
      min-width: 1.04rem
      padding: 0 .1rem
      float: right
      text-align: center
      color: #fff
      .arrow-icon
        margin-left: .04rem
        font-size: .24rem複製程式碼

Vue—去哪兒筆記


Vuex的高階用法:(程式碼優化)

 {{this.$store.state.city}}
複製程式碼

這時候我們使用公用資料,需要通過 {{this.$store.state.city}} 這樣一長串才能獲取到我們要的city資料。

Vuex中提供了一個比較高階的API,

首先我們引入mapState

import { mapState } from 'vuex'複製程式碼

之後我們來一個計算屬性

computed: {
    ...mapState(['city'])
  }
複製程式碼

...mapState(['city'])  把vuex裡面的city共用資料對映到該元件的名叫city的computed計算屬性裡。做好對映後,就可以 用 {{this.city}} 來獲取city資料了。

傳遞內容可以是個陣列,也可以是個物件。

 computed: {
    ...mapState({
      currentCity: 'city'
    })
  }
複製程式碼

對映後的計算屬性名字就叫 currentCity 啦。所以我們通過 {{this.currentCity}}來獲取資料。

 handleCityClick(city) {
      this.$store.commit('changeCity',city)
      this.$router.push('/')
    }
複製程式碼

當我們點選城市按鈕的時候,會通過commit方法 派發一個mutations,Vuex同樣提供了一個簡便的API mapMutations

同樣使用引入mapMutations

methods: {
    handleCityClick(city) {
      this.changeCity(city)
      this.$router.push('/')
    },
    ...mapMutations(['changeCity'])
  },
複製程式碼

有一個mutations叫做changeCity,然後把這個mutations對映到元件裡的一個叫做changeCity方法裡,我們呼叫mutations就可以直接呼叫cahngeCity()這個方法啦。


Vuex有幾個核心的概念,state存放公用資料,actions用於寫些非同步方法或者同步批量操作,mutations用於寫些同步地對資料地改變。Vuex中還提供了 getters API,他的作用有點類似於元件中的computed計算屬性的作用,當我們需要根據 state 裡面的資料算出一些新的資料就可以藉助 getter 來提供新的資料,避免資料的冗餘。

getters: {
     doubleCity (state) {
           return state.city + ' ' + state.city 
     }
}複製程式碼

computed: {
    ...mapGetters(['doubleCity'])
  }複製程式碼

當我們遇到一個非常複雜的業務場景,比如說我們在管理後臺系統的時候,經常會有很多公用的資料在vuex裡面進行儲存,這樣mutations檔案會變得非常龐,難以維護。這個時候可以藉助module對一個複雜的state,mutations,actions進行拆分。建立store的時候可以通過module來對store的建立。

const moduleA = {
  state: { ... },
  mutations: { ... },
  actions: { ... },
  getters: { ... }
}

const moduleB = {
  state: { ... },
  mutations: { ... },
  actions: { ... }
}

const store = new Vuex.Store({
  modules: {
    a: moduleA,
    b: moduleB
  }
})

store.state.a // -> moduleA 的狀態
store.state.b // -> moduleB 的狀態複製程式碼

這樣做,A模組只要儲存和A模組相關的資料和資料的操作就可以了,然後在建立store時候再對各個模組的資料進行整合。

十四. 使用keep-alive優化網頁效能

Vue—去哪兒筆記

我們開啟chrome 下的Network 切換到XHR,會發現我們切換一次頁面就會請求一次資料,原因是每次路由切換到一個元件的時候,這個元件就會被重新渲染,它的mounted()鉤子就會被執行,那麼ajax資料就會重新獲取。這樣每次切路由都重新獲取一次資料會大大的降低效能。

我們只要在App.vue這個專案根元件的路由 <router-view/> 外包裹<keep-alive>

<keep-alive>
    <router-view/>
 </keep-alive>
複製程式碼

這樣,路由的內容被載入過一次後就把路由的內容放到記憶體中,下一次再進這個路由的時候,不需要重新渲染這個元件,只需要去取記憶體中內容顯示就可以啦。

這個時候其實我們程式碼還存在一些問題,當我們選擇城市後,再路由到首頁後,首頁的內容是不會變化的。

我們可以通過vuex,將ajax請求路徑為相應城市

 axios.get('/static/mock/index.json?city=' + this.city)複製程式碼

但是,因為我App.vue路由中新增了keep-alive 後,就算選擇了不同的城市,頁面也不會被重新渲染了。

那我們如何去改變快取裡的資料呢?方法1:當我們使用keep-alive的時候,元件裡會多出一個生命週期函式activated()(keep-alive 元件啟用時呼叫activated),當頁面重新被顯示的時候執行activated,在activad()裡判斷選擇的城市是否被改變,改變了就重新傳送ajax請求。

方法2:加個exclude,這個組將就不會進行快取了。

<keep-alive exclude="Detail">
      <router-view/>
</keep-alive>
複製程式碼

十五.動態路由

path: '/detail/:id'

vue中路徑後加 :id 為動態路由

十六.對全域性事件的解綁

在上一節中,我們對window做了事件的繫結

activated () {
    window.addEventListener('scroll', this.handleSroll)
  }
複製程式碼

如果,我們在某個元件的標籤上繫結了某個事件,只作用於這個元件,不會對外部元件產生任何的影響。但是,在這個元件裡寫的是對window這個全域性事件的繫結,在該頁面關閉時就需要對其解綁。那如何解綁呢?當我i們對這個元件用了keep-alive的時候,元件會提供 activated 生命週期鉤子,在每次頁面展示的時候被執行。與之對應,還提供了一個叫 deactivated生命週期鉤子,在頁面即將被隱藏,或者即將被替換成其他頁面的時候,deactivated就會被執行。

deactivated () {
    window.removeEventListener('scroll', this.handleSroll)
  }
複製程式碼

也就是,頁面展示的時候繫結scroll事件,頁面被隱藏的時候,對scroll事件解綁。

十七.使用遞迴元件實現詳情頁列表

每個元件的  name  的作用是什麼?

1.當我們做遞迴元件的時候,會用到name

<template>
  <div>
     <detail-list></detail-list>
  </div>
</template>

export default{
	name: 'DetailList'
}複製程式碼

2.當我們在也頁面上想對某個頁面取消快取的時候

<keep-alive exclude="Detail">
      <router-view/>
</keep-alive>複製程式碼

3.vue-devtool除錯


相關文章