Vue—去哪兒筆記

項目代碼css

一.項目環境準備html

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

下面來介紹下vue項目目錄html5

README.md  項目說明文件node

package.json  項目開發須要的第三方依賴包webpack

LICENSE 開源協議的說明ios

index.html  項目默認首頁文件git

.prostcssrc.js github

.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>
複製代碼

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主分支上。


而後在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>複製代碼


當輪播圖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組件。


點擊的聯動(點擊城市列表頁的右側字母表,左側的列表會自動地滾動到頁面的顯示區域之中)點擊觸發事件右側字母子組件,獲取字母(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>複製代碼


如今咱們想經過點擊「熱門城市」來改變「當前城市」,就是公用城市也要跟着變化,那該怎麼作呢?(改變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變得複雜起來了。爲了易讀性和可維護性,咱們能夠對代碼進行拆分。怎麼拆分這裏就很少說啦。



有的時候由於城市名的長度,首頁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複製代碼



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優化網頁性能


咱們打開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調試

相關文章
相關標籤/搜索