vue-create-api个人理解

962 阅读1分钟

介绍

本文用作个人学习记录

核心作用: 能让vue组件通过api方式调用的插件; 用法介绍:

image-20211209114517632.png

源码理解

这里主要是基于cube-ui和vue-create-api源码进行create-api原理的解析

首先cube-ui中使用create-api的方式:

export default function createAPI (Vue, Component, events, single) {
  Vue.use(createAPIComponent, {componentPrefix: 'cube-'})
  const api = Vue.createAPI(Component, events, single)
  return api
}

然后会在cube-ui组件(modules文件夹下)中使用:

export default function addDialog (Vue, Dialog) {
  createAPI(Vue, Dialog, ['confirm', 'cancel', 'close', 'btn-click', 'link-click'], true)
}

接下来我们解释下上面代码的含义,在Vue.use中会执行vue-create-api中导出的install方法,代码如下:

function install(Vue, options = {}) {
  const {componentPrefix = '', apiPrefix = '$create-'} = options

  Vue.createAPI = function (Component, events, single) {
    if (isBoolean(events)) {
      single = events
      events = []
    }
    const api = apiCreator.call(this, Component, events, single)
    const createName = processComponentName(Component, {
      componentPrefix,
      apiPrefix,
    })
    Vue.prototype[createName] = Component.$create = api.create
    return api
  }
}

这里会在 Vue 构造器下添加一个 createAPI 方法。提供三个参数,Component 组件、 events 事件数组、 single 是否采用单例模式实例化组件。最后将api.create赋给Component.$createVue.prototype[createName],这也是为什么调用组件有两种方式的原因。

function processComponentName(Component, options) {
  const {componentPrefix, apiPrefix} = options
  const name = Component.name
  assert(name, 'Component must have name while using create-api!')
  const prefixReg = new RegExp(`^${escapeReg(componentPrefix)}`, 'i')
  const pureName = name.replace(prefixReg, '')
  let camelizeName = `${camelize(`${apiPrefix}${pureName}`)}`
  return camelizeName
}

这是processComponentName方法源码,所以使用create-api的组件一定要声明name属性,要不然会报错。

然后我们看下install返回的的api到底是什么,看下apiCreator方法也就是creator.js文件。这也是最核心的部分,接下来解析整体的处理流程:

首先我们看最基本方法内容:

image-20211209114517633.png

可以看到这个方法输出的是一个api,那么这个api是什么呢,我们可以看下:

image-20211209171314394.png 里面定义了两个方法before和create方法,before方法是一个钩子函数会在组件创建的时候被调用,create方法则是被调用的方法。

下面看create方法的实现:

image-20211209192151243.png 这里是判断是否是使用this.createComponent调用还是使用Component.createComponent调用还是使用Component.create调用。

然后看核心执行部分:

image-20211209192820772.png

解析数据

先是处理了用户传入的config,parseRenderData将用户传入的配置遍历分类,分离出props和on对象(源码如下)。

image-20211209195043023.png

image-20211209193659118.png

image-20211209194042932.png

events是调用createAPI是传入的config是使用组件时传入的。

这里遍历选出传入的配置中是否有events中定义的事件名,然后加到on对象中,events会被parseEvents处理加上on前缀和驼峰命名。

监听参数

image-20211209195424188.png

image-20211209195404137.png

使用vue原型的方式调用的话,如果依赖了实例的响应数据则使用vue的实例方法$watch监听,指定对应回调函数onChange。同时也把数据给到renderData(渲染数据)中。

监听事件

image-20211209200624772.png

image-20211209200646475.png

如果传入的是string则寻找vue实例上定义的方法,给到renderData。

自定义组件配置

image-20211209201539678.png

可以使用$开头的自定义配置,同样会加到renderData中,后续会给到createElement方法的第二个参数创建组件。

创建组件实例

image-20211209201819949.png

image-20211209202130144.png

主要做了几件事:

  • 判断是否需要使用单例
  • 创建组件实例
  • 给组件添加方法,控制展示(show hide remove)

最后看下如何创建组件实例:

image-20211209204115075.png

创建一个Vue实例,使用createElement传入处理完的配置创建Vnode,更新渲染数据,执行$mount和init挂载真实DOM到body上。

最后回到creator.js文件,监听’hook:beforeDestroy‘销毁监听事件和实例。

image-20211209204831320.png

参考文档

介绍文档:didi.github.io/cube-ui/#/z…

开源库:github.com/cube-ui/vue…

create-api:juejin.cn/post/684490…