3

状态与变更
export default new Vuex.Store(
{ state: { count:0 },
mutations: { add(state) { state.count++ } }
})

派生状态
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']) }
}

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.js

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
}

HappyCodingTop
526 声望847 粉丝

Talk is cheap, show the code!!


« 上一篇
vue-router 细入
下一篇 »
Notice组件实现