vue2.0探索之路--vuex使用場景和集成

 emmm...一直在猶豫要不要寫這篇博客,因爲覺得這些內容官網已經介紹的很詳細了,再複述一遍貌似沒太多意義。後面想了下,不復述、總結,如何加深自己的印象和理解呢,畢竟老年人,記性越來越差了。所以,開始吧。

一、概述

   vuex是一個專爲Vue.js應用程序開發的狀態管理模式。 它採用集中式存儲管理應用的所有組件的狀態,並以相應的規則保證狀態以一種可預測的方式發生變化。

二、使用場景

  我相信很多人都和我一樣,在使用vuex之前都會想一個問題(如果你一開始就很明確自己對vuex的需求,那麼恭喜你,你很棒棒),爲什麼要用vuex????這玩意有啥好的,除了聽着高大上點,狀態管理,那麼具體能給我的項目帶來什麼好處啊,而且我改怎麼用它。下面就來簡單說說我的理解。

狀態管理,就是管理的全局變量。在我們的項目中,特別是較大型的項目,會有很多參數是很多地方都會用到的,比如,一個登錄的token,很多頁面都需要這個信息,當然我們可以時刻在對應頁面操作cookie,但是有這麼個統一管理的地方,爲啥不用呢。所以,狀態管理不是必需的,所有狀態管理能做的,都能用其他方式實現,但是狀態管理提供了統一管理的地方,操作方便,也更加明確。但是別啥都往裏頭扔了,一些只是父組件和子組件用到的,能用$emit和props簡單實現的,就用這個就行了。

三、集成

先貼上我的集成代碼:

目錄結構


index.js爲總入口


getters:state中的狀態獲取


user.js


api中爲請求統一封裝


下面開始對vuex的相關功能做個總結,詳情請參考:vuex官網

1. state

存在mapState輔助函數,見第六小結

import Vue from 'vue';
import App from './App';
import store from './store/index'
import './mock/mock';

import router from './router';

import './ui.js'

/* 公共服務平臺*/
import 'static/platform/css/common.less';

var vm = new Vue({
    el: '#app',
    router,
    store,
    template: '<App/>',
    components: {App}
});

在根組件註冊store之後,可以在組件中通過this.$store.state.count訪問state中的count參數,在模塊中,需要在state後面加上模塊名,詳情見第五小節。

2.Getter

有時候我們需要從store中的state中派生出一些狀態,可以通過在store中定義getter(可以看作store的計算屬性),Getter接受state作爲第一個參數 ,也可以接受其他getter作爲第二個參數。存在輔助函數mapGetters,見第六小結

const store = new Vuex.Store({
  state: {
    todos: [
      { id: 1, text: '...', done: true },
      { id: 2, text: '...', done: false }
    ]
  },
  getters: {
    doneTodos: state => {
      return state.todos.filter(todo => todo.done)
    }
  }
})

然後可以通過以下方式訪問
this.$store.getters.doneTodos

3. Mutation

 提交mutation是修改store中的狀態的唯一方法。通過提交mutation,vue能監控到數據的變化,然後動態更新節點。

定義:

const store = new Vuex.Store({
  state: {
    count: 1
  },
  mutations: {
    increment (state) {
      // 變更狀態
      state.count++
    }
  }
})

調用(可傳入第二個參數作爲入參):

store.commit('increment')

對象風格的提交方式:

store.commit({
  type: 'increment',
  amount: 10
})

也可以使用常量替代Mutation事件類型

//mutation-types.js
export const SOME_MUTATION = 'SOME_MUTATION';

// store.js
import Vuex from 'vuex'
import { SOME_MUTATION } from './mutation-types'

const store = new Vuex.Store({
  state: { ... },
  mutations: {
    // 我們可以使用 ES2015 風格的計算屬性命名功能來使用一個常量作爲函數名
    [SOME_MUTATION] (state) {
      // mutate state
    }
  }
})

需要注意:Mutation必須是同步函數

4.Action

Action類似於mutation,不同在於:

1.Action提交的是mutation,而不是直接變更狀態;

2.Action可以包含異步操作。

示例:

const store = new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    increment (state) {
      state.count++
    }
  },
  actions: {
    increment (context) {
      context.commit('increment')
    }
  }
})

action函數接受一個與store實例具有相同方法和屬性的context對象。可以使用參數解構簡化代碼:

actions: {
  increment ({ commit }) {
    commit('increment')
  }
}

分發Action:

store.dispatch('increment')

異步操作:

actions: {
  checkout ({ commit, state }, products) {
    // 把當前購物車的物品備份起來
    const savedCartItems = [...state.cart.added]
    // 發出結賬請求,然後樂觀地清空購物車
    commit(types.CHECKOUT_REQUEST)
    // 購物 API 接受一個成功回調和一個失敗回調
    shop.buyProducts(
      products,
      // 成功操作
      () => commit(types.CHECKOUT_SUCCESS),
      // 失敗操作
      () => commit(types.CHECKOUT_FAILURE, savedCartItems)
    )
  }
}

存在mapActions輔助函數,詳見第六小結

5.Module

爲了解決store對象隨着項目開發會越來越臃腫,vuex允許將store分割成模塊,每個模塊擁有自己的state、mutation、action、getter、甚至是嵌套子模塊--從上至下進行同樣方式的分割。例如

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 的狀態

6.輔助函數

mapState

普通寫法:

// 在單獨構建的版本中輔助函數爲 Vuex.mapState
import { mapState } from 'vuex'

export default {
  // ...
  computed: mapState({
    // 箭頭函數可使代碼更簡練
    count: state => state.count,

    // 傳字符串參數 'count' 等同於 `state => state.count`
    countAlias: 'count',

    // 爲了能夠使用 `this` 獲取局部狀態,必須使用常規函數
    countPlusLocalState (state) {
      return state.count + this.localCount
    }
  })
}

或者

mapState([
 // 映射 this.count 爲 store.state.count
'count'
])

對象展開運算符

computed: {
  localComputed () { /* ... */ },
  // 使用對象展開運算符將此對象混入到外部對象中
  ...mapState({
    // ...
  })
}

mapGetters

import { mapGetters } from 'vuex'

export default {
  // ...
  computed: {
  // 使用對象展開運算符將 getter 混入 computed 對象中
    ...mapGetters([
      'doneTodosCount',
      'anotherGetter',
      // ...
    ])
  }
}

mapActions

import { mapActions } from 'vuex'

export default {
  // ...
  methods: {
    ...mapActions([
      'increment', // 將 `this.increment()` 映射爲 `this.$store.dispatch('increment')`

      // `mapActions` 也支持載荷:
      'incrementBy' // 將 `this.incrementBy(amount)` 映射爲 `this.$store.dispatch('incrementBy', amount)`
    ]),
    ...mapActions({
      add: 'increment' // 將 `this.add()` 映射爲 `this.$store.dispatch('increment')`
    })
  }
}

四、最後

總算總結完了,又加深了一遍記憶,還是很好的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章