iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 18
0
Modern Web

30天手把手的vue.js教學!系列 第 18

2020it邦鐵人賽-30天手把手的Vue.js教學 Day18- 建立簡單的store集中管理資料吧!

tags: Vue.js ItIron2020

前言

我們在昨天的文章介紹了event bus的概念,截至目前為止關於資料管理我們已經學到了

  • 父子層元件的溝通(props & emit)
  • 水平組件間的溝通(EventBus,當然不僅限於同一層級)

今天我們要延續資料管理的議題,像各位介紹store的概念,為之後的vuex鋪路!

我不是已經會EventBus了嗎? 為什麼我還需要另一套資料管理的方式?

確實EventBus已經解決了大多資料管理的問題,透過跨組件的溝通已經可以讓我們的應用程式順利運作,設置上也相當的簡單,用於小型專案時可說是非常好的解決方案。不過隨著專案規模變大,很多時候不同的組件間我們需要使用相同的資料,像是登入的使用者、從後端請求的資料,你會發現光靠EventBus你很難去追蹤那些資料,這時候store的概念就幫得上忙了。利用將資料集中管理在一個物件內,有需要的人自己去取、更新,至始至終所有人用的都是同一份資料,自然也就不用去擔心資料不同步的問題囉!

store核心概念

store的核心概念相當單純,它就像是一個管理資料的倉庫,所有資料的存放、變動都需要在這個倉庫完成,你不能、也不應該在其他地方變動倉庫的資料。 你可能會感到困惑,如果是這樣的話,是不是表示我們就不能在組件中去改變資料,這樣要怎麼更新畫面? 是的,你不能在組件中直接改變倉庫的資料,不過你可以在組件中發送一個事件給倉庫,讓倉庫知道它該改動資料了!
隨著主題的延續,你會漸漸發現props、emit、eventbus到現在的store以及未來的vuex都是彼此相連的概念,這點到我們之後介紹完vuex時應該會更有感觸的!

實作簡單的store

我們一樣接續昨天的範例,請你先在src下新增一個store.js檔案,並寫入以下的內容。

export const store = {
  state: {
     numbers: [1,2,3,5,7]
  }
}

store一點也不特別,它就是一個單純的物件而已,state則是一個慣例的寫法,其實就只是表示資料,也就是目前整個應用程式的資料狀態。

接著請你回到src/DisplayNumbers.vue,將程式碼修改為以下

<template>
  <div>
    <h2>{{ numbers }}</h2>
  </div>
</template>

<script>
import { EventBus } from '../EventBus.js'
import { store } from '../store.js'

export default {
  data() {
    return {
      numbers: [1,2,3,5,7]
    }
  },
  methods: {
    handleAddNumber() {
      EventBus.$on('addNumber',(payload)=>{
        this.numbers.push(payload)
      })
    }
  },
  created() {
    this.handleAddNumber()
    console.log(store)
  }
}
</script>

我們加入了store的引入與印出,運行npm run serve後你應該會看到以下的畫面。
demo-1

你可以看到store的資料毫不意外地呈現在console中,既然我們已經取得資料了,接著我們就不需要在這個組件的numbers data,我們直接從store取出來用就好了! 相信聰明的你應該知道要做什麼了,請將上方的程式碼改為以下的寫法

<template>
  <div>
    <h2>{{ storeState }}</h2>
  </div>
</template>

<script>
import { store } from '../store.js'

export default {
  data() {
    return {
      storeState: store.state.numbers
    }
  }
}

我們從store取出的物件不能直接在template上render(它不屬於vue實體),所以要記得先將它存在data變數中再嵌到template,完成後你應該會發現....頁面完全沒有變化

no-difference

這很正常,我們只是將資料管理的方式改變,本來就預期會達到一樣的效果XD

接著我們需要處理資料變動的部分,還記得我們剛提過所有資料的變動都只能在倉庫內進行嗎? 這表示我們需要另一個屬性來儲存所有的操作,請你回到src/store.js,新增以下的程式碼

export const store = {
  state: {
    numbers: [1, 2, 3, 5, 7],
  },
  addNumber(newNumber) {
    this.state.numbers.push(parseInt(newNumber))
  },
}

藉由觸發addNumber函數去更新state.numbers的值,同時因為子元件是綁定顯示state.numbers,畫面也會同步更新! 理解到這一點後,我們最後的工作就是在AddNumbers.vue中引入store並執行這樣的操作,請你將AddNumbers.vue的程式碼改為以下

<script>
import { store } from '../store.js'

export default {
  data() {
    return {
      number: 0
    }
  },
  methods: {
    addNumber() {
      store.addNumber(this.number)
    }
  }
}
</script>

上方template的部分則完全不用改變,在這個組件中,我們並非直接修改state的值,正如我們之前說的一樣,是呼叫store內的方法進行更新!
玩玩看現在的程式,你應該會發現程式仍順利運作囉!

結語

今天的文章就到這邊為止,我們介紹了store的基本概念與應用,至此你已經有著兩種處理跨組件溝通的方式,很明顯的可以看出store可以更輕鬆的追蹤所有的資料,同時藉由將所有的操作都集中在store中,你可以避免一些意外的情況發生,在維護時也會較為方便! 我們之後會延續這樣的概念介紹一個好用的套件,敬請期待~!

此文章同步發布於個人部落格,有興趣的大大也可以來參觀一下:D


上一篇
2020it邦鐵人賽-30天手把手的Vue.js教學 Day17 - 認識EventBus,實現子層組件間的相互溝通
下一篇
2020it邦鐵人賽-30天手把手的Vue.js教學 Day19 - 認識vuex(上)
系列文
30天手把手的vue.js教學!30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
xiangtain
iT邦新手 5 級 ‧ 2020-12-22 14:23:10

最後一段改scirpt寫錯了 應該是更改AddNumbers.vue 不是DisplayNumbers.vue

感謝提醒,已修正誤植的部分!

我要留言

立即登入留言