rottenpen / day-day-study

记录自己每天学了什么的blog
0 stars 0 forks source link

3.20.2020 #2

Open rottenpen opened 4 years ago

rottenpen commented 4 years ago

TODO:

  1. 手写 vuex ☑️
  2. 算法题 ✖️
rottenpen commented 4 years ago

手写vuex

let Vue

// const isObject = (obj) => {
//   return obj !== null && typeof obj === 'object'
// }
// const isPromise = (val) => {
//   return val && typeof val.then === 'function'
// }

// function forEachValue (obj, fn) {
//   Object.keys.forEach(key => {
//     fn(obj, obj(key))
//   })
// }
function forEachValue (obj, fn) {
  // debugger
  Object.keys(obj).forEach(function (key) { return fn(obj[key], key) })
}

function unifyObjectStyle (type, payload, options) {
  if (typeof type === 'object' && type.type) {
    options = payload
    payload = type
    type = payload.type
  }
  return {
    type,
    payload,
    options
  }
}

class Store {
  constructor (options) {
    this.vm = {
      state: Vue.observable(options.state)
    }
    this.getters = Object.create(null)
    this.actions = Object.create(null)
    this.mutations = Object.create(null)
    const store = this
    // TODO: 依赖值变化的时候就变化,可以 store.getters.xxx 直接获得值,不需要另外运行函数,可以接受其他 getter 作为参数
    const getters = options.getters || {}
    forEachValue(getters, (fn, key) => {
      Object.defineProperty(getters, key, {
        get: function (state) {
          return fn(store.state, store.getters)
        }
      })
    })
    // TODO: mutations 传一个 state 一个 payload 用于同步调用
    const mutations = options.mutations || {}
    forEachValue(mutations, (fn, key) => {
      this.mutations[key] = (payload) => {
        fn(this.state, payload)
      }
    })

    // TODO: actions 传入一个 state 一个 payload 用于异步调用 在异步函数里想同步更新 state 需要再调用 mutations
    const actions = options.actions || {}
    forEachValue(actions, (fn, key) => {
      this.actions[key] = (payload) => {
        fn(this, payload)
      }
    })
  }

  get state () {
    return this.vm.state
  }

  set state (v) {
    console.error('不能直接赋值 state')
  }

  commit (_type, _payload, _options) {
    const { type, payload, options } = unifyObjectStyle(_type, _payload, _options)
    this.mutations[type](payload)
    console.log(options)
  }

  dispatch (_type, _payload, _options) {
    const { type, payload, options } = unifyObjectStyle(_type, _payload, _options)
    this.actions[type](payload)
    console.log(options)
  }
}
// TODO: 一些辅助函数 用于映射 getters actions mutations
const mapGetters = () => {}
const mapActions = () => {}
const mapMutations = () => {}

const install = (_Vue) => {
  // 证明之前已经安装了一次 vue store了
  if (Vue && _Vue === Vue) {
    return
  }
  Vue = _Vue
  applyMixin(Vue)
}

function applyMixin (_Vue) {
  // 为所有的 vue 组件植入 $store
  _Vue.mixin({
    beforeCreate: vueInit
  })
  function vueInit () {
    const options = this.$options
    if (options.store) { // 在根元素 App.vue 里引入包内的 store 类
      this.$store = typeof options.store === 'function'
        ? options.store()
        : options.store
    } else if (options.parent && options.parent.$store) { // 自组件就直接用父组件的 $store 就可以了
      this.$store = options.parent.$store
    }
  }
}

export default {
  install,
  Store,
  mapActions,
  mapGetters,
  mapMutations
}

vuex 的功能模块

  1. install ☑️
  2. dispatch ☑️
  3. commit ☑️
  4. getters, mutations, actions ☑️
  5. 映射部分 mapGetters, mapMutations, mapActions ✖️
  6. module ✖️