Vuex的簡單實現

根據本身所學知識,實現一個low版本Vuexhtml

第一步 分析

  1. 做爲一個Vue插件,須要實現install方法,詳情參考這裏
  2. 在日常使用的過程是,是Vuex.Store,因此要實現這個方法,同時還須要接收傳入的配置 options
  3. 有四個數據,分別是state,mutations,actions,getters,還有一個commitdispatch方法
  4. 明確各項任務
    1. state 數據
    2. mutations 負責改變數據
    3. getters獲得數據
    4. actions,執行異步,提交mutations

第二步 框架搭建

Store方法

options.getters && this.handleGetters(options.getters)vue

這個方法是在調用的時候發現有getters,就執行這個函數返回結果vuex

let Vue

class Store {
  constructor (options = {}) {
    this.state = new Vue({ data: options.state })
    this.$options = options
    this.mutations = options.mutations || {}
    this.actions = options.actions
    options.getters && this.handleGetters(options.getters)
  }

  commit = (type, arg) => { 
      
  }

  dispatch (type, arg) {
    
  }

	// 控制getters方法
  handleGetters (getters) {
    
  }
}

// install方法
function install (_vue) {
  Vue = _vue // 會返回一個vue實例
  Vue.mixin({
    beforeCreate () {
      if (this.$options.store) { // 負責掛載
        Vue.prototype.$store = this.$options.store
      }
    }
  })
}

export default {
  Store,
  install
}
	
複製代碼

install方法

function install (_vue) {
  Vue = _vue // 會返回一個vue實例
  Vue.mixin({
    beforeCreate () {
      if (this.$options.store) { // 負責掛載
        Vue.prototype.$store = this.$options.store
      }
    }
  })
}
複製代碼

第三步 具體實現

commit方法

commit = (type, arg) => { // 默認指向定義它時,所處上下文的對象的this指向
    this.mutations[type](this.state, arg)
  }
複製代碼

這個這叫好理解,從mutations裏獲取道咱們因此要的方法,而後傳遞參數,值得注意的是this,指向框架

dispatch

dispatch (type, arg) {
    this.actions[type]({ // this表明着它的直接調用者
      commit: this.commit,
      state: this.state
    }, arg)
  }
複製代碼

這個也比較簡單,不作敘述了異步

handleGetters

handleGetters (getters) {
    this.getters = {}
    // Object.keys 返回 getters對象的key
    Object.keys(getters).forEach(key => {
      // 參考網址 https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty
      Object.defineProperty(this.getters, key, {
        get: () => {
          return getters[key](this.state)
        }
      })
    })
  }
複製代碼

Object.keys參考

參考網址ide

定義一個對象,循環拿到對應的函數名稱,而後向這個對象上定義 函數名稱的屬性,增長get方法。 傳進來的getters是一個對象模塊化

第四步 完整代碼

let Vue

class Store {
  constructor (options = {}) {
    this.state = new Vue({ data: options.state })
    this.$options = options
    this.mutations = options.mutations || {}
    this.actions = options.actions
    options.getters && this.handleGetters(options.getters)
  }

  commit = (type, arg) => { // 默認指向定義它時,所處上下文的對象的this指向
    this.mutations[type](this.state, arg)
  }

  dispatch (type, arg) {
    this.actions[type]({ // this表明着它的直接調用者
      commit: this.commit,
      state: this.state
    }, arg)
  }

  handleGetters (getters) {
    console.log(getters)
    this.getters = {}
    // Object.keys 返回 getters對象的key
    // 參考網址 https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/keys
    Object.keys(getters).forEach(key => {
      // 參考網址 https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty
      Object.defineProperty(this.getters, key, {
        get: () => {
          return getters[key](this.state)
        }
      })
    })
  }
}

function install (_vue) {
  Vue = _vue // 會返回一個vue實例
  Vue.mixin({
    beforeCreate () {
      if (this.$options.store) { // 負責掛載
        Vue.prototype.$store = this.$options.store
      }
    }
  })
}

export default {
  Store,
  install
}

複製代碼

store裏面的代碼

import Vue from 'vue'
import Vuex from './../myvuex'

Vue.use(Vuex)

export default new Vuex.Store({
  state: { // 狀態
    count: 0
  },
  mutations: { // 改變狀態
    increment (state, n = 1) {
      state.count += n
    }
  },
  getters: {
    score (state) {
      return `一個共${state.count}`
    }
  },
  actions: { // 複雜的邏輯 作異步操做 參考網址 https://vuex.vuejs.org/zh/guide/actions.html
    incrementAsync ({ commit }) {
      setTimeout(() => {
        commit('increment', 2) // 提交一個mutations
      }, 1000)
    }
  },
  modules: { // 模塊化
    // 具體參考https://vuex.vuejs.org/zh/guide/modules.html
  }
})

複製代碼
相關文章
相關標籤/搜索