DAY27 | 跟 Vue.js 認識的30天 - Vue 套餐之圖書館 Vuex (上)

了解了如何創建基礎的 Vue Router 後,就應該來學學如何利用 Vuex 來進行全域狀態管理。

為什麼要使用 Vuex

Vuex 官網是這麼介紹:

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。

在之前沒有 Vuex 的時候,如果要讓子模組 B 取的父模組 A 的資料,我們可以透過 Vue 的 props 屬性來完成,

現在假設模組 B 跟模組 C 都在模組 A 中,但模組 B 跟模組 C 有一筆共用的資料,此時模組 B 變更這筆資料,如何讓模組 C 該筆資料同時間發生改變呢?

如果沒有 Vuex ,要怎麼達成資料連動?
來看下圖:

解決方法:

  • 第一種

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    <div id="vm">
    <component-b :data1="msg" @changemsg="getNewMsg"></component-b>>
    <component-c :data1="msg"></component-c>>
    </div>
    <script>
    Vue.component('componentB',{
    props: ['data1'],
    template:`<div>
    <p>{{ data1 }}</p>
    <button @click.prevent="changeProps">按鈕改變資料</button>
    </div>`,
    methods:{
    changeProps(){
    this.$emit('changemsg','改變的資料')
    }
    }
    })

    Vue.component('componentC',{
    props: ['data1'],
    template:`<div>
    <p>{{ data1 }}</p>
    </div>`,
    })

    const vm = new Vue({
    el: '#vm',
    data:{
    msg: '我是資料'
    },
    methods:{
    getNewMsg(newMsg){
    this.msg = newMsg
    }
    }
    })
    </script>
  • 第二種

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    <div id="vm">
    <component-b></component-b>>
    <component-c></component-c>>
    </div>
    <script>
    // 在 Vue 的原型鏈中新增 $bus ,$bus 的值為一個 Vue 實例
    Vue.prototype.$bus = new Vue()

    Vue.component('componentB',{
    template:`<div>
    <p>componentB:{{ data1 }}</p>
    <button @click.prevent="changeProps">按鈕改變資料</button>
    </div>`,
    data(){
    return {
    data1: ''
    }
    },
    methods:{
    changeProps(){
    // 透過 $bus 中的 $emit 傳遞資料
    this.$bus.$emit('changemsg','改變的資料')
    this.data1 = '改變的資料'
    }
    }
    })

    Vue.component('componentC',{
    template:`<div>
    <p>componentC:{{ data1 }}</p>
    </div>`,
    data(){
    return {
    data1: ''
    }
    },
    created(){
    // 透過 $bus 中的 $on 接收資料
    this.$bus.$on('changemsg', msg => {
    this.data1 = msg
    })
    }
    })

    const vm = new Vue({
    el: '#vm',
    })
    </script>

props 的筆記可參考:DAY12 | 跟 Vue.js 認識的30天 - Vue 模組資料傳遞(props)

emit 的筆記可參考:DAY13 | 跟 Vue.js 認識的30天 - Vue 模組自定義事件(Custom Events)

不論是哪一種方法看起來都很麻煩,對吧!一定要記得哪個模組是傳遞及哪個模組是接收,但如果使用 Vuex 就可以避免這些情況了。

Vuex 的概念就是建立一個集中管理的資料庫,不論哪個模組需要連動的資料都可以向 Vuex 取得。

安裝

Vuex 提供幾種安裝的方法:

  • 使用 CDN (免下載)

    1
    2
    3
    4
    <!-- 開發版 -->
    <!--先載入 Vue 在載入 Vue Router-->
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script src="https://unpkg.com/vuex@3.6.2/dist/vuex.js"></script>
  • 使用 NPM

    1
    $ npm install vuex --save

    記得使用 ↓↓↓ 載入

    1
    2
    3
    4
    import Vue from 'vue'
    import Vuex from 'vuex'

    Vue.use(Vuex)

Demo

See the Pen DAY27 | 跟 Vue.js 認識的30天 - Vue 套餐之圖書館 Vuex (上) by Celeste6666 (@celeste6666) on CodePen.

參考資料

Vuex