What is Vuex? 祝你快速上手

前言

文章涉及的內容可能不全面,但量不少,須要慢慢看。我花了很長的時間整理,用心分享心得,但願對你們有所幫助。可是不免會有打字的錯誤或理解的錯誤點,但願發現的能夠郵箱告訴我1163675970@qq.com,我會及時的進行修改,只但願對你有所幫助,謝謝。javascript

1、 Vuex 是什麼?

Vuex 是一個專門爲 vue.js 應用程序開發的狀態(狀態就是數據)管理模式,它採用集中式存儲管理應用的狀態。至關於把組件中的數據提高到一個全局的地方,這個地方就是 Vuex 的 store(倉庫),由 Vuex 統一管理,vue

若是某個組件須要這個數據,直接從 store 中獲取。 若是要修改存在 Vuex 中的數據,須要在定義 store 時,定義修改這個數據的方法,這些方法稱爲 mutation;java

  • mutation 函數的第一個參數是 state 對象,全部的數據都定義state中,在 mutation 函數中經過 state 能夠修改 上面 state 中的數據;
  • 注意 mutation 中修改數據只能使用同步的方式,不能再異步的操做中更新數據;若是有異步就須要使用action;
  • action 也是更新數據的方式,action 不一樣於 mutation 的是 action 可使用異步,可是更新數據仍然須要 commit 對應的 mutation;

2、使用 Vuex 的步驟

  • 在此以前,你須要安裝 Vuex,若是是 vue-cli ,在初始化項目時選擇 Vuex 把須要放到 Vuex 中的數據存在 state 裏面
  1. 建立修改這些數據的 mutation
  2. 若是這些數據須要異步更新,則建立對應的 action , 而且在 action 中經過 commit mutation 的方式更新數據
  3. 最後導出 Vuex 的 stroe 實例,而且爲 Vue 的根實例配置 store 屬性,配置 store 屬性後,在 Vue 實例中能夠經過 this.$store 訪問 store
  4. 在整個 Vue 的應用中,任何地方須要使用該數據,經過 this.$store.state.屬性名 的方式獲取數據;
  5. 若是須要更新這些數據能夠經過調用 this.$store.commit(mutation函數名),若是是異步更新,須要 this.$store.dispatch(action名)

3、示例:

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

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    // state 就是數據,若是數據定義在 state 中組件中若是要使用這個數據 this.$store.state.屬性名 的方式獲取
    num: 15
  },
  mutations: {
    // state 中的數據不能被直接修改,若是要修改這些數據,須要使用 mutation,注意 mutation 中不能使用異步更新 state
    add (state) {
      // mutation 函數的第一個參數是 state 對象,全部的數據都定義 state 中,在 mutation 函數中經過 state 能夠修改 上面 state 中的數據;
      state.num++
    },
    addNum (state, payload) {
      // mutation 的第二個參數 payload 是在 commit mutation 時傳入的參數
      state.num += payload
    }
  },
  actions: {
    // action 可使用異步,可是更新數據仍然須要 commit 對應的 mutation
    asyncAdd(context) {
      setTimeout(() => {
        context.commit('add')
      }, 1000)
    }
  }
})
複製代碼
  • App.vue
<template>
  <div id="app"> <div id="nav"> <router-link to="/">Home</router-link> | <router-link to="/about">About</router-link> <h1>someNum: {{$store.state.num}}</h1> </div> <router-view/> </div> </template> <script> import Bus from './bus' export default { name: 'App', data () { return {} } } </script> 複製代碼
  • Home.vue
<template>
  <div class="home">
    <img alt="Vue logo" src="../assets/logo.png">
    <div>
      <button @click="add">給上面的sumNum加加</button>
      <button @click="add2">給上面的sumNum加2</button>
    </div>
  </div>
</template>

<script>

export default {
  name: 'home',
  methods: {
    add () {
      this.$store.commit('addOne') // commit mutation
      this.$store.dispatch('asyncAdd') // dispatch action
    },
    add2 () {
      this.$store.commit('addNum', 2) // 傳遞 payload
    }
  }
}
</script>
複製代碼

4、mapState/mapMutations/mapActions

若是使用不少個 store 中的數據和方法時經過 this.$store 的方式很不方便,Vuex 提供了三個對應的方法用於批量獲取多個 state、mutation、action;vuex

<script>
// @ is an alias to /src
import HelloWorld from '@/components/HelloWorld.vue'
// import Bus from '../bus'

import { mapState, mapMutations, mapActions } from 'vuex'

export default {
  name: 'home',
  methods: {
    updateX (e) {
      this.$store.commit('changeX', e.target.value)
    },
    updateSex(e) {
      this.$store.commit('changeSex', e.target.value)
    },
    add () {
       this.addOne() // 等效於 this.$store.commit('addOne')
    },
    add2 () {
       this.addNum(2); // 等效於 this.$store.commit('addNum', 2)
    },
    add3 () {
       this.asyncAdd2(); // 等效於 this.$store.dispatch('asyncAdd')
    },
    ...mapMutations(['addOne', 'addNum']),
    ...mapActions({
      asyncAdd2: 'asyncAdd' // 重命名
    })

  },
  computed: {
    ...mapState(['num'])
  },
  components: {
    HelloWorld
  }
}
</script>
複製代碼
  • 經過 mapState、mapMutations、mapActions 方法結合展開運算符,能夠把對應的數據和方法添加到computed 和 methods 中的,這些數據方法均可以經過 this 實例訪問

5、在項目中使用 vuex

  • 我的建議,若是這個數據被多處依賴了最好使用 Vuex,而不是全部的數據都交給 Vuex 託管;
  • Vue 書城首頁的 輪播圖、熱門圖書使用 Vuex
  • store.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
import * as homeActions from './model/home'
export default new Vuex.Store({
   state: {
      slides: [],
      hotBooks: []
   },
   mutations: {
      fillSides (state, payload) {
         state.slides = payload
      },
      fillHotBooks (state, payload) {
         state.hotBooks = payload
      }
   },
   actions: {
      async getSliders ({ commit }) {
         commit('fillSides', await homeActions.getSliders())
      },
      async getHotBooks ({ commit }) {
         commit('fillHotBooks', await homeActions.getHot())
      }
   }
})
複製代碼
  • Home.vue
<template>
  <div >
    <MyHeader>首頁</MyHeader>
    <div class="content">
      <swiper :sliders="slides"></swiper>
      <div class="container">
        <h2>熱門圖書</h2>
        <ul class="container">
          <li v-for="(book, index) in hotBooks" :key="index">
            <img :src="book.bookCover" alt="">
            <b>
              {{book.bookName}}
            </b>
          </li>
        </ul>
      </div>
    </div>
  </div>
</template>
<script>
// @ is an alias to /src
import MyHeader from '@/components/MyHeader.vue'
import swiper from '@/components/Swiper.vue'
// import { getSliders, getHot } from '../model/home'
import { mapState, mapActions } from 'vuex'
export default {
  name: 'home',
  data () {
   return {}
  },
  computed: {
    // slides 和 hotBooks 經過 mapState 從 Vuex store 中獲取
    ...mapState(['slides', 'hotBooks'])
  },
  created () {
    // 經過 Vuex 獲取圖書和輪播信息
    this.getSliders();  // this.$store.dispatch('getSliders')
    this.getHotBooks();  // this.$store.dispatch('getHotBooks')
  },
  methods: {
    ...mapActions(['getSliders', 'getHotBooks'])
  },
  components: {
   MyHeader,
    swiper
  }
}
</script>
<style scoped lang="less">
  .container {
    box-sizing: border-box;
    overflow-x: hidden;
    h2 {
      padding-left: 30px;
    }
    ul li {
      float: left;
      width: 50%;
      margin: 20px 0;
      img {
        display: block;
      }
      b {
        padding-left: 30px;
      }
    }
  }
</style>
複製代碼

大家利用強大的vuex的過人之處在哪?歡迎留言評論區見

相關文章
相關標籤/搜索