Vue.js
ItIron2020
我們在昨天的文章介紹了event bus的概念,截至目前為止關於資料管理我們已經學到了
今天我們要延續資料管理的議題,像各位介紹store的概念,為之後的vuex鋪路!
確實EventBus已經解決了大多資料管理的問題,透過跨組件的溝通已經可以讓我們的應用程式順利運作,設置上也相當的簡單,用於小型專案時可說是非常好的解決方案。不過隨著專案規模變大,很多時候不同的組件間我們需要使用相同的資料,像是登入的使用者、從後端請求的資料,你會發現光靠EventBus你很難去追蹤那些資料,這時候store的概念就幫得上忙了。利用將資料集中管理在一個物件內,有需要的人自己去取、更新,至始至終所有人用的都是同一份資料,自然也就不用去擔心資料不同步的問題囉!
store的核心概念相當單純,它就像是一個管理資料的倉庫,所有資料的存放、變動都需要在這個倉庫完成,你不能、也不應該在其他地方變動倉庫的資料。 你可能會感到困惑,如果是這樣的話,是不是表示我們就不能在組件中去改變資料,這樣要怎麼更新畫面? 是的,你不能在組件中直接改變倉庫的資料,不過你可以在組件中發送一個事件給倉庫,讓倉庫知道它該改動資料了!
隨著主題的延續,你會漸漸發現props、emit、eventbus到現在的store以及未來的vuex都是彼此相連的概念,這點到我們之後介紹完vuex時應該會更有感觸的!
我們一樣接續昨天的範例,請你先在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後你應該會看到以下的畫面。
你可以看到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,完成後你應該會發現....頁面完全沒有變化
這很正常,我們只是將資料管理的方式改變,本來就預期會達到一樣的效果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
最後一段改scirpt寫錯了 應該是更改AddNumbers.vue 不是DisplayNumbers.vue
感謝提醒,已修正誤植的部分!