使用vuexStore.registerModule构建命令式组件

Front End Js Vue

命令式组件

例如Notification, MessageBox, Alert, ConfirmBox 等等

这类组件都是通过命令式来调用.

例如elementUithis.$message或者Message来调用.

对于我们来说,this.$message这种调用方法莫过于是最方便.因为不需要处处引入Message或者在webpack中配置插件使得Message暴露于全局

那么我就从this.$message这类讲起

组件编写

其实也只是编写一个Comp组件, 这里不多说.

接入方式

第一种接入方式

Vue组件挂载到一个dom上,也就是将组件实例化.

然后将组件实例挂载命名空间中或者Vue.prototype中,

这样相当于直接操作组件实例的methods来改变组件的状态.

ElementUI使用的是这种方式.

无入侵式

第二种接入方式

这方式前提必须要使用Vuex, 因为他是依赖vuex.registerStore实现

关于registerStore请移步到文档

其实就是动态注册一个storeModule, 用来管理组件的状态.

所有操作都通过细改store的状态来引起组件的改变

// 引入组件
import Comp from 'Comp.vue'
function registerModule(store) {
  store.registerModule('compNameSpaceState', {
    namespaced: true,
    state: {},
    getters: {},
    mutations: {},
    actions: {}
  })
}

之后可以将通过对象将调用接口暴露出去

let $compApi = function() {
  return {
    // 此处需要使用建投函数,确保this指向
    action: () => {
      this.$store.dispatch('compNameSpaceState/compAction')
    }
  }
}

接下来很简单,就是将$compApi.prototype中.

那么如何保证$compApithis指向Vue实例呢

let bind = false
// Vue.use() 会自动调用install方法,此时可以注册组件
Comp.install = function(Vue) {
  // 代理带vue原形上.可以通过this.$spin调用
  Object.defineProperties(Vue.prototype, {
    $compApi: {
      // 挂载到Vue.prototype中的$compApi
      get() {
        if (!bind) {
          // 注册store
          registerModule(this.$store)
          // 只需要绑定一次即可
          // 绑定后可以将原来的$compApi覆盖掉
          // 调用bind函数确保this指向
          $compApi = $compApi.bind(this)()
          bind = true
        }
        return $compApi
      }
    }
  })
  // 将组件注册为Vue全局组件
  Vue.component('Comp', Comp)
}
export default Comp

最后一步则需要在App.vue将Comp挂载上去

// 这一步自动调用install, 会全局注册Comp
// 但是在第一次调用$compApi时候才会进行registerStore.
Vue.use(Comp)
<!-- App.vue-->
<template>
  <Comp />
</template>

这种方法是入侵式的

但是可以很方便的追踪组件状态, 而且实现起来也很方便.

在自己开发组件的时候可以考虑