Vuex 的細入

狀態與變動
export default new Vuex.Store(
{ state: { count:0 },
mutations: { add(state) { state.count++ } }
})vue

派生狀態
export default new Vuex.Store(
{ getters: { todoCount(state) {
return state.todos.filter(todo=>!todo.completed).length } }
})
異步操做
export default new Vuex.Store({ actions: { someAction(context) { // do something context.state;
//訪問狀態 context.commit()
// 提交變動 context.dispatch();// 派發動做 } } })
簡化方法
export default { computed: { ...mapState(['isLogin']), ...mapGetters(['loginState']) },
methods: { ...mapActions(['login']) }
}vuex

import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const cart = {
  state: {
    list: []
  },
  mutations: {
    addCart (state, good) {
      const ret = state.list.find(v => v.id === good.id)
      if (ret) {
        ret.count += 1
      } else {
        state.list.push({good, count: 1, active: true})
      }
    }
  }
}
export default new Vuex.Store({
  state: {
    isLogin: false
  },
  getters: {
    loginState (state) {
      return state.isLogin ? '歡迎回來as' : '遊客'
    }
  },
  mutations: {
    login (state) {
      state.isLogin = true
    }
  },
  actions: {
    //   {commit}就是結構賦值
    requestLogin (contxt, payload) {
      console.log(contxt)
      console.log(payload)
      // 異步操做,成功與否告訴外界
      return new Promise(resolve => {
        setTimeout(() => {
          contxt.commit('login')
          resolve(true)
        }, 1000)
      })
    }
  },
  modules: {
    cart
  }
})

vuex在vue中源碼實現

YStore.jsapp

import Vue from 'vue'
class YStore {
  constructor (options) {
    this.state = options.state
    this.mutations = options.mutations
    this.actions = options.actions
    // 借用Vue自己數據響應機制
    this.vm = new Vue({
      data: {
        state: this.state
      }
    })
  }
  commit (type, payload) {
    const mutation = this.mutations[type]
    mutation(this.state, payload)
  }
  dispatch (type, payload) {
    const action = this.actions[type]
    const ctx = {
      commit: this.commit,
      state: this.state,
      dispatch: this.dispatch
    }
    return action(ctx, payload)
  }
}
export default new YStore({
  state: {count: 1},
  mutations: {
    add (state) {
      state.count++
    }
  }
})

組件中使用異步

<template>
  <div id="app">
    {{getNum}}
    <button @click="onAdd">add</button>
  </div>
</template>

<script>
import store from './YStore'
export default {
  name: 'App',
  computed: {
    getNum () {
      return store.state.count
    }

  },
  methods: {
    onAdd () {
      store.commit('add')
    }
  }
}
</script>

真正的源碼

**Vuex也是一個插件
實現四個東西:state,mutations/actions/getters
建立Store
數據響應式**函數

let vue
function install (_vue) {
  Vue = _vue
  // 這樣store執行的時候,就有了vue,不用import
  // 這也是爲啥vue.use必須在新建store以前
  Vue.mixin({
    beforeCreate () {
      // 這樣才能獲取到傳遞進來的store
      // 只有root元素纔有store,因此判斷一下
      if (this.$options.store) {
        Vue.prototype.$store = this.$options.store
      }
    }
  })
}
class Store {
  constructor (options = {}) {
    this.state = new Vue({
      data: options.state
    })
    this.mutations = options.mutations || {}
    this.actions = options.actions
    options.getters && this.handleGetters(options.getters)
  }
//   注意這裏用箭頭函數形式,後面的action實現時會有做用
commit = (type, arg) => {
  this.mutations[type](this.state, arg)
}
dispatch = () => {
  this.actions[type]({commit: this.commit, state: this.state}, arg)
}
handleGetters (getters) {
  this.getters = {} // 定義this.getters
  //   遍歷getters選項,爲this.getters定義property
  //   屬性名就是選項中的key,只須要定義get函數保證其只讀性
  Object.keys(getters).forEach(key => {
    Object.defineProperty(this.getters, key, {
      get: () => { // 注意依然是箭頭函數
        return getters[key](this.state)
      }
    })
  })
}
}

export default {
  Store, install
}
相關文章
相關標籤/搜索