大白話理解和初步使用vuex

TL;DR

  • 單向數據流是state => view => action => state,而view是不能直接改變state的
  • vuex就是數據管理,全部數據的修改都必須寫成方法,放在mutations,只能經過store.commit('xxmutation')修改數據
  • state/getters/mutations/actions,state注意沒有s,代碼裏mapState/mapGetters/mapMutations/mapActions
  • actions常和請求使用,配合async和await
  • v-model注意在computed那邊設置getter setter

單向數據流是啥

<div>
  <h1>{{title}}</h1>
  <button @click="handleClick">將標題第一個字母大寫</button>
<div>
複製代碼
  • 大白話版:js的data裏寫了title => h1那邊能顯示出來,點擊按鈕 => js裏method執行 => data的title的第一個字母大寫了 => h1那邊再次顯示出來
  • 專業名詞版:state => view => action => state (和上面一一對應,感覺下)
  • 圖片版:
    單向數據流的解釋

其實數據不復雜的狀況下,method就夠用的。數據複雜以後,就有點雲裏霧裏了。固然組件傳遞數據很麻煩的狀況下,vuex也是方便不少。css

vuex,其實就是管理數據的,全部數據的變化都必須經過方法add(1),不能直接xx.a=4這種。而後就是專有名詞和具體用法須要記憶了。html

vuex的專業名詞

vuex的官網vuex的apivue

vuex的專業名詞:ios

  • store,看代碼new Vuex.Store({state:{},mutations:{}}),store是倉庫,存着數據,存着改變數據的方法。
  • state,就是數據,至關於datastate:{title:'hi'}
  • getter,state派生出一些狀態,至關於computed,但computed是經過this拿到data,而這裏是經過參數訪問store的state和getters,getters:{ doneTodosCount: (state,getters)=>{return getters.doneTodos.length} }
  • mutation,相似於事件,至關於method,仍是經過參數拿到state,參數直接放後面,mutations:{ add(state,n){ state.count + n } },調用的時候,store.commit('add',10),發現沒,傳方法名和參數就能夠了,不用傳state~
  • action,上面的mutation只能同步,若是有異步,就須要用action了,可是改變數據,只能commit(mutation),action的參數和上面都不同,其是store實例,能夠拿到store因此的東西,但通常commit居多,actions:({ add({commit}){commit('add')} }),觸發的方式store.dispatch('add'),這樣感覺不到異步的特殊性,換種方式
actions: {
  incrementAsync ({ commit }) {
    setTimeout(() => {
      commit('increment')
    }, 1000)
  }
}
複製代碼

action這邊,其實特別重要,由於請求基本都是異步的,這邊寫下,結合請求使用actionvuex

state:{
  listData:[]
},
mutations:{
  setListData(state,data){
    state.listData = data
  }
},
// 另外的文件裏,export function getList(){ return axios.get('/list').then(res => res.data)}
actions: {
  async setListData ({ commit }) {
    commit('setListData', await getList())
  },
  async setOtherListData ({ dispatch, commit }) {
    // 若是有串聯請求 先請求這個
    await dispatch('setListData')
    commit('setOtherListData', await getOtherList())
  }
}

// 順便寫下 若是延時改變
actions: {
  actionA ({ commit }) {
    // 處理異步操做 當選promise
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        commit('someMutation')
        resolve()
      }, 1000)
    })
  },
  actionB ({ dispatch, commit }) {
    return dispatch('actionA').then(() => {
      commit('someOtherMutation')
    })
  }
}
// 組件裏 1s以後變值
store.dispatch('actionA').then(() => { ... })
// 或者
store.dispatch('actionB')
複製代碼
  • module,全部的狀態都在一個store裏,可能漸漸就龐大了,和css相似,能夠將store分割成模塊,每一個模塊有本身的state、mutation、action、getter甚至是嵌套子模塊。
const moduleA = { state: { ... }, mutations: { add(state,n){state.count+n} }, actions: { ... }, getters: { ... } }
const moduleB = { state: { ... }, mutations: { ... }, actions: { ... } }
const store = new Vuex.Store({
  modules: {
    a: moduleA,
    b: moduleB
  },
  state:{}
})
store.state.a // -> moduleA 的狀態
store.state.b // -> moduleB 的狀態
複製代碼

代碼裏怎麼使用vuex

首先store是掛載在vue實例上的,因此全部的組件都能訪問到store,new Vue({store})axios

組件裏訪問state

/* xx.vue v1.0.0 */
computed: {
  count () {
    // count就是在store那邊
    // Vuex 經過 store 選項,提供了一種機制將狀態從根組件「注入」到每個子組件中,這樣子組件經過this.$store就能夠訪問
    return this.$store.state.count
  },
  isLogin () {
    return this.$store.state.isLogin
  }
}

/* 可是當屬性不少的時候,這樣寫太冗餘了 用數組簡化下 v2.0.0 */
let res = {}
['count', 'login'].map(prop => { res[prop] = () => this.$store.state[prop] })
// 用的時候
computed:{...res}
 
/* 索性能夠定義成一個方法 v3.0.0 */
function mapState(propArr){
  let res = {}
  propArr.map(prop => { res[prop] = () => this.$store.state[prop] })
  return res
}
// 用的時候
computed:{...mapState(['count', 'login'])}

/* 固然咱們能想到的,vuex早就替咱們想到了,因此vuex本身提供了mapState v4.0.0 */
// 固然mapState還能夠對象形式,能夠去官網看看
import { mapState } from 'vuex'
computed:{...mapState(['count', 'login'])}
複製代碼

組件裏訪問getters

用法同state,不贅述。api

import { mapGetters } from 'vuex'
computed:{...mapGetters(['count', 'login'])}
複製代碼

組件裏訪問mutations

其實知道state的用法,這邊就簡單多了,兩種形式,下面也寫個例子:數組

// mutation怎麼寫的 回憶下 add(state,n){state.count+n}

/* 1. 直接組件裏 this.$store.commit('add',1) */

/* 2. 組件裏 把mutation放進methods */

methods:{
  add (n) {
    this.$store.commit('add', n)
  }
}
// 多個的話
import { mapMutations } from 'vuex'
methods:{
  ...mapMutations(['add'])
}

複製代碼

組件裏訪問actions

用法同mutations,不贅述。promise

/* 1. 直接組件裏 this.$store.dispatch('add',1) */

/* 2. 組件裏 把actions放進methods */
import { mapActions } from 'vuex'
methods:{...mapActions(['add'])}
複製代碼

特別注意v-model

v-model會直接改變數據,違背了vuex,因此不能像以前那樣寫,換個寫法異步

// <input v-model="message">

// store.js
mutations: {
  updateMessage (state, message) {
    state.obj.message = message
  }
}

// xx.vue
computed: {
  message: {
    get () {
      return this.$store.state.obj.message
    },
    set (value) {
      this.$store.commit('updateMessage', value)
    }
  }
}
複製代碼

vuex使用必須記住的

  • 應用層級的狀態應該集中到單個 store 對象中。

  • 提交 mutation 是更改狀態的惟一方法,而且這個過程是同步的。

  • 異步邏輯都應該封裝到 action 裏面。

相關文章
相關標籤/搜索