1:狀態管理和使用場景(vuex):vue
vuex所解決的問題與bus相似,它做爲Vue的一個插件使用,能夠更好的管理和維護整個項目的組件狀態。
在實際的業務邏輯中,常常有跨組件共享數據的須要,所以Vuex的設計就是用來更好的管理統一管理組件狀
態的。它定義了一系列規範來使用和操做數據,使組件應用更加高效。ios
1.1: Vuex的基本使用? 1.1.1: 首先經過NPM進行安裝: npm install --save vuex 1.1.2: 在main.jsl文件裏,經過Vuer.use()使用Vuex import Vuex from 'vuex' import createrLogger from 'vuex/dist/logger' const debug = process.env.NODE_ENV !== 'production' Vue.use(Vuex) 1.1.3: 進行路由配置 const store = new Vuex.Store({ // vuex的配置 state: { count: 0, list: [1, 5, 8, 10, 30, 50] }, mutations: { increment (state) { state.count++; }, decrease (state, n = 1) { // n= n || 1 state.count -= n; }, ceshiTypeFunc (state, params) { state.count += params.count; } }, actions: { increase (context) { context.commit('increase'); }, asyncIncreasement(xontext) { return new Promise((resolve, reject) => { this.$nextTick(() => { contect.commit('increase'); resolve(); }) }) } } getters: { filterList: state => { return state.list.filter(item => item< 10); }, listCount: (state, getters, rootState) => { // rootState.count 來訪問根節點的狀態。 return getters.filterList .length; } }, plungins: debug ? [crateLogger()] : []; }); 倉庫store包含了應用的數據(狀態)和操做過程。Vuex裏面的數據都是響應式的,在任何組件使用同一store的數據 時候,只要store的數據變化的時候,對應的組件也會當即更新。 在任何組件中,能夠直接經過$store.state.count讀取。(模板),直接寫在template中會顯得會很亂, 可使用一個 計算屬性來進行顯示: export default { computed: { count() { return this.$store.state.count; }, list() { return this.$store.state.list.filter(item => item < 10); }, listTwo() { return this.$store.getters.filterList; }, listCount() { return this.$store.getters.listCount; } } } 1.1.4: 狀態值更改? 在組件中,來自store的數據只能進行讀取,不能手動更改, 改變store中的數據的時候惟一途徑是使用顯示的提交 mutations(mutations是Vuex的第二個選項, 用來直接修改state裏的數據). 在組件中使用this.$store.commit方法來進行執行mutations中的方法的(例如點擊事件) methods: { handIncrease () { this.$store.commit('increase'); }, handDecrease () { this.$store.commit('decrease'); }, handCeshiFunc () { this.$store.commit({ type: 'ceshiTypeFunc ', count: 10 }); }, handActionIncrease() { this.$store.dispatch('increase'); }, handAsyncIncreasement() { this.$store.dispatch('asyncIncreasement ').then(() => { console.log(this.$store.state.count); }) } } 這樣看起來就像Javascript的觀察者模式,組件只負責提交一個事件名, Vuex對應的mutations來完成業務邏輯。 mutation還能夠接受第二個參數, 能夠是數字、字符串或者對象等。 注意,mutation裏儘可能不要使用異步操做數據, 若是異步操做數據,組件在commit後,數據不會當即更新,並且不知 道何時改變。 1.1.5: 高級用法? Vuex還有其餘3個選項可使用: getters、actions、modules. getters: 若是隻是想獲得小於10的數據, 最容易想到的是經過計算屬性進行過濾,這樣寫是沒有問題的,可是若是是 其餘組件也要使用過濾後的數據的時候,就得吧computed的代碼徹底複製一份了,並且當須要修改過濾方法 的時候,每一個用到的組件都須要進行修改,這明顯很差, 所可使用getters. 注意: getters也能夠依賴其餘的getters,把getters做爲第二個參數。 actions: actions與mutation很像,不一樣的是action裏面提交的是mutations,而且能夠異步操做業務邏輯。 action在組建內經過$store.dispatch觸發。 modules: module將store分割到不一樣的模塊,當你的項目足夠大的時候,store裏的state、getters、mutations、 actions會分廠多,放再main.js裏面顯得不是很友好,使用modules能夠將它們寫到不一樣的文件裏面,每一個 modules都擁有本身的state、getters、mutations、actions,並且能夠多層嵌套。 const modulesA = { state: { ... }, mutations: { ... }, actions: { ... }, getters: { ... } } const modulesB = { state: { ... }, mutations: { ... }, actions: { ... }, getters: { ... } } const store = new Vuex.Store({ modules: { a: modulesA, b: modulesB } }) 1.1.6: 比較? mutations、actions看起來很類似,可能會以爲不知道哪一個, 可是Vuex很像是一種與開發者的約定,因此涉及 改變數據的,就使用mutations,存在業務邏輯的就用actions.至於將業務邏輯放在你action裏仍是Vue組件裏完 成的根據實際的業務邏輯拿捏。 1.2: 輔助函數? Vuex除了提供咱們Store對象以外,還對外提供了一系列的輔助函數,方便咱們在代碼中使用Vuex,提供了操做store 的各類屬性的一系列的語法糖。 1.2.1: mapState mapState工具函數會將store中的state映射到局部計算中,爲了更好的理解它的實現。
前:(對象)
import { mapState } from 'vuex'
export default {vuex
computed: mapState({ count: state => state.count, // 傳入字符串‘count’ 等同於`state => state.count` countAlia: 'count', // 想要訪問局部狀態,就必須藉助於一個普通函數,函數中使用`this`獲取局部狀態。 countPlusLocalState (state) { return state.count + this.localCount; } })
}
通過mapStore函數調用以後的結果:
import {mapState} from 'vuex'
export default {npm
computed: { count() { return this.$store.state.count; }, countAlia () { return this.$store.state['count']; }, countPlusLocalState () { return this.$store.state.count + this.localCount } }
前:(數組)
import { mapState } from 'vuex'
export default {數組
computed: mapState([ 'count' ])
}
通過mapStore函數調用以後的結果:
import {mapState} from 'vuex'
export default {app
computed: { count() { return this.$store.state['count']; } }
當計算屬性名稱和狀態子樹名稱對應相等的時候,咱們能夠向,mapState工具函數中傳入一個字符串數組。
computed: mapState({dom
// 映射this.count 到 this.$store.state.count 'count'
});異步
經過例子能夠明顯看出來mapState函數能夠接受一個對象,也能夠接受一個數組。 1.2.2: mapGetters mapGetters工具函數將store中的getters映射到局部計算屬性屬性中,它的功能和mapsState很是相似
前(數組)
import { mapGetters } from 'vuex'
export default {async
computed: { ...mapGetters([ 'doneTodoCount', 'anotherGetter', // ... ]) }
}
通過mapGetters 函數調用以後的結果:
import { mapGetters } from 'vuex'
export default {函數
computed:{ doneTodoCount () { return this.$store.getters['doneTodoCount ']; }, anotherGetter() { this.$store.getters['anotherGetter ']; } }
}
前(對象)
computed: mapGetters({
doneCount: 'doneTodosCount'
})
通過mapGetters 函數調用以後的結果:
computed: {
doneCount() {
return this.$store.getters['doneTodosCount ']
}
}
1.2.3: mapActions mapActions工具函數將store中的dispatch方法映射到組件的methods中,和mapState、mapGetters相似,只不過 它映射的是地方不是計算屬性,而是組件的methods對象上面:
前
import {mapActions} from 'vuex'
export default {
methods: { ...mapActions([ 'increase' // 映射this.increase() 到 this.$store.dispatch('increase'); ]), ...mapActtions([ add: 'increase' // 映射 this.add() 到 this.$store.dispatch('increase'); ]) }
}
通過mapActions 函數調用以後的結果:
import { mapActions } from 'vuex'
export default {
methods:{ increase(...arg) { return this.$store.dispatch.apply(this.$store, ['increase'].concat(args)) }, add(...arg) { return this.$store.dispatch.apply(this.$store, ['increase'].concat(args)); } }
}
1.2.4: mapMutations: mapMutations 工具函數會將store中的commit方法映射到組件的methods中,和mapActions的功能幾乎同樣
前
import { mapMutatiosn } from 'vuex'
export default {
methods: { ...mapMutatiosn ([ 'increase' // 映射this.increase() 到 this.$store.commit('increase'); ]), ...mapMutatiosn ([ add: 'increase' // 映射 this.add() 到 this.$store.commit('increase'); ]) }
}
通過mapMutatiosn 函數調用以後的結果:
import { mapMutatiosn } from 'vuex'
export default {
methods:{ increase(...arg) { return this.$store.commit.apply(this.$store, ['increase'].concat(args)) }, add(...arg) { return this.$store.commit.apply(this.$store, ['increase'].concat(args)); } }
}
1.3: 插件 Vuex的store接受一個plung 選項,一個Vuex的插件就是一個簡單的方法,接受store做爲惟一的參數。 插件的做用一般阿是用來監聽每次mustations的變化的,來作一些事情。 在store的構造函數的最後,咱們經過以下代碼調用插件。
import devtoolPlungin from './plungins/devtool'
plungins.concat(devtoolPlungin).forEach(plungin => plungin(this))
2: 中央事件總線的使用(vue-bus)
在本地目錄下建立目錄vue-bus,在目錄vue-bus下插件vue-bus.js文件,此時就給Vue添加了一個屬性$bus,而且代理了$emit, $on,$off三個方法, 代理以下
// vue-bus.js
const install = function(Vue) {
const Bus = new Vue({ methods: { emit(event, ...args) { this.$emit(event, ...args); }, on(event, ...args) { this.$on(event, ...arg); }, off(event, callback) { this.$off(event, callback); } } }); Vue.prototype.$bus = Bus;
}
export default install;
使用:
// 在main.js 文件中使用
import VueBus from './vue-bus'; Vue,use(VueBus);
// 在view中仙劍一個組件Counter.vue
接收前
<template> <div> {{number}} </div> <button @click="handAddRandom">隨機增長<button> </template> <script> export default { props: { number: { type:Number } }, methods: { handleAddRandom() { // 隨機回去0-100之間的數值 const num = Math.floor(Match.random() * 100 + 1); this.$bus.emit('add', num); } } } </script>
接收後
<template> <div> <Counter :number="number"></Counter> </div>
·</template>
import Counter from './conter.vue' <script> export default { componrents: { Counter }, data: { return : { number: 0 } }, methods: { handlerAddRandom(num) { this.number = num; } } created() { this.$bus.on('add', this.handlerAddRandom ) }, beforeDestory() { this.$bus.off('add', this.handlerAddRandom) } } </script>