標籤:-- mit 解釋 操作 選型 script ofo cli github
前言
之前幾個項目中,都多多少少碰到一些組件之間需要通訊的地方,而因為種種原因,
event bus 的成本反而比vuex還高, 所以技術選型上選用了 vuex, 但是不知道為什麼,
團隊裡的一些新人一聽到vuex,就開始退縮了, 因為vuex 很難? 真的很難嗎?
今天我們用簡單的3步來證明一下,vuex有多簡單.
純屬個人經驗,難免有不正確的地方,如有發現,歡迎指正!這是一個針對新手的入門級教程、入門級教程、入門級教程
第零步
建立一個vue項目,安裝vuex,這裡不做過多介紹,能點進來的,預設你具備這些技能 ^_^
第一步
建立一個.js 檔案,名字位置任意,按照慣例,建議在/src/store 目錄下(沒有的話自己建立一個唄)
檔案位置 /src/store/index.js
// 引入vue 和 vueximport Vue from 'vue'import Vuex from 'vuex'// 這裡需要use一下,固定寫法,記住即可Vue.use(Vuex)// 直接匯出 一個 Store 的執行個體export default new Vuex.Store({ // 類似 vue 的 data state: { name: 'oldName' }, // 類似 vue 裡的 mothods(同步方法) mutations: { updateName (state) { state.name = 'newName' } }})
代碼看起來稍微有那麼一點點多,不過看起來是不是很熟悉? 跟普通的 vue 沒多大差別嘛.
這一步其實就是建立一個store,但是我們還沒在項目中使用.
第二步
在入口檔案引入上述檔案, 並稍微改一下傳給 new Vue()的參數,新增的行後面有備忘
檔案位置 /src/main.js (vue-cli自動產生的入口,如果你能不用腳手架,那麼也就不需要我說明了)
import Vue from 'vue'import App from './App'import vuexStore from './store' // 新增new Vue({ el: '#app', store:vuexStore // 新增 components: { App }, template: '<App/>'})
Tip: import store from ‘./store‘ 後面的地址,就是上面我們建立那個檔案的位置(
/src/store/index.js),
因為我這裡是index.js,所以可以省略.
第三步
以上2步,其實已經完成了vuex的基本配置,接下來就是使用了
檔案位置 /src/main.js (同樣是vue-cli產生的app.vue,這裡為了方便示範,我去掉多餘的代碼)
<template> <div> {{getName}} <button @click="changeName" value="更名">更名</button> </div></template><script>export default { computed:{ getName(){ return this.$store.state.name } }, methods:{ changeName () { this.$store.commit('updateName') } }}</script>
這裡就是一個很普通的vue檔案了,有區別的地方是這裡我們需要用computed屬性去擷取 store 裡的 "data"
還有就是我們要改變資料的話,不再用 this.xxx = xxx 改成 this.$store.commit(‘updateName‘)
總結
你可能會覺得,上例這樣做的意義何在,為何不直接用vue的data跟methods?
上例只是為了簡單講解如何使用vuex,所以簡化了一些流程,試想一下,如果你有這樣一個頁面:
一共嵌套了10層組件(即子組件裡面還有子子組件,子子組件下面還有子子子組件,以此類推10層)
然後最後一層組件一個資料改變了,要通知第一層組件的時候,我們只需在最底層組件裡this.$store.commit(),
然後再最外層組件上用computed屬性擷取對應的值,就能做到即時更新.無需層層$emit上去.
最後
本來想在最後再擴充一下getter,action+dispatch,模組化等等,不過為了對得起這個標題,
只好放在 下一篇:vuex其實超簡單,喝完這3步,還有3步
vuex其實超簡單,喝完這3步,還有3步
上一篇 vuex其實超簡單,只需3步
簡單介紹了vuex的3步入門,不過為了初學者容易消化,我削減了很多內容,這一節,就是把少掉的內容補上,
如果你沒看過上篇,請戳連結過去先看一下再回來,否則,你會覺得本文摸不著頭腦.
純屬個人經驗,難免有不正確的地方,如有發現,歡迎指正!
還是一樣,本文針對初學者.
一、
Getter
我們先回憶一下上一篇的代碼
computed:{ getName(){ return this.$store.state.name }}
這裡假設現在邏輯有變,我們最終期望得到的資料(getName),是基於 this.$store.state.name
上經過複雜計算得來的,剛好這個getName要在好多個地方使用,那麼我們就得複製好幾份.
vuex 給我們提供了 getter,請看代碼 (檔案位置 /src/store/index.js)
import Vue from 'vue'import Vuex from 'vuex'Vue.use(Vuex)export default new Vuex.Store({ // 類似 vue 的 data state: { name: 'oldName' }, // 類似 vue 的 computed -----------------以下5行為新增 getters:{ getReverseName: state => { return state.name.split('').reverse().join('') } }, // 類似 vue 裡的 mothods(同步方法) mutations: { updateName (state) { state.name = 'newName' } }})
然後我們可以這樣用 檔案位置 /src/main.js
computed:{ getName(){ return this.$store.getters.getReverseName }}
事實上, getter 不止單單起到封裝的作用,它還跟vue的computed屬性一樣,會緩衝結果資料,
只有當依賴改變的時候,才要重新計算.
二、
actions和$dispatch
細心的你,一定發現我之前代碼裡 mutations 頭上的注釋了 類似 vue 裡的 mothods(同步方法)
為什麼要在 methods 後面備忘是同步方法呢? mutation只能是同步的函數,只能是同步的函數,只能是同步的函數!!
請看vuex的解釋:
現在想象,我們正在 debug 一個 app 並且觀察 devtool 中的 mutation 日誌。每一條 mutation 被記錄,
devtools 都需要捕捉到前一狀態和後一狀態的快照。然而,在上面的例子中 mutation 中的非同步函數中的回調讓這不
可能完成:因為當 mutation 觸發的時候,回呼函數還沒有被調用,devtools 不知道什麼時候回呼函數實際上被調
用——實質上任何在回呼函數中進行的狀態的改變都是不可追蹤的。
那麼如果我們想觸發一個非同步操作呢? 答案是: action + $dispatch, 我們繼續修改store/index.js下面的代碼
檔案位置 /src/store/index.js
import Vue from 'vue'import Vuex from 'vuex'Vue.use(Vuex)export default new Vuex.Store({ // 類似 vue 的 data state: { name: 'oldName' }, // 類似 vue 的 computed getters:{ getReverseName: state => { return state.name.split('').reverse().join('') } }, // 類似 vue 裡的 mothods(同步方法) mutations: { updateName (state) { state.name = 'newName' } }, // 類似 vue 裡的 mothods(非同步方法呼叫) -------- 以下7行為新增 actions: { updateNameAsync ({ commit }) { setTimeout(() => { commit('updateName') }, 1000) } }})
然後我們可以再我們的vue頁面裡面這樣使用
methods: { rename () { this.$store.dispatch('updateNameAsync') }}
三、
Module 模組化
當項目越來越大的時候,單個 store 檔案,肯定不是我們想要的, 所以就有了模組化.
假設 src/store 目錄下有這2個檔案
moduleA.js
export default { state: { ... }, getters: { ... }, mutations: { ... }, actions: { ... }}
moduleB.js
export default { state: { ... }, getters: { ... }, mutations: { ... }, actions: { ... }}
那麼我們可以把 index.js 改成這樣
import moduleA from './moduleA'import moduleB from './moduleB'export default new Vuex.Store({ modules: { moduleA, moduleB }})
這樣我們就可以很輕鬆的把一個store拆分成多個.
四、
總結
- actions 的參數是
store 對象,而 getters 和 mutations 的參數是 state .
- actions 和 mutations 還可以傳第二個參數,具體看vuex官方文檔
- getters/mutations/actions 都有對應的map,如: mapGetters , 具體看vuex官方文檔
- 模組內部如果怕有命名衝突的話,可以使用命名空間, 具體看vuex官方文檔
- vuex 其實跟 vue 非常像,有data(state),methods(mutations,actions),computed(getters),還能模組化.
vuex其實超簡單,只需3步