公共模块

1

基础模块参照了vant的思路,使用bem命名规范。先创建一个命名空间,这个命名空间返回创建组件函数与生成命名方法。在创建组件函数中创建nameinstall属性用于注册vue组件

创建组件函数

创建base组件

npm run plop
# 输入组件名称得到packages/base模块

在src文件夹中创建create文件夹并创建component.ts文件用于创建组件方法。创建组件与要name属性和install方法来注册组件

/**
 * Create a basic component with common options
 */
import { App, defineComponent, ComponentOptionsWithObjectProps } from 'vue'

/**
 *
 * @description 创建组件
 * @export createComponent
 * @param {string} name
 * @return {*} defineComponent
 */
export function createComponent (name: string) {
  return function (sfc: ComponentOptionsWithObjectProps) {
    sfc.name = name
    sfc.install = (app: App) => {
      app.component(name as string, sfc)
      app.component(name), sfc)
    }

    return defineComponent(sfc)
  } as typeof defineComponent
}

因为我们组件名字可能包含多个单词所以我们把他转换为驼峰命名法所以创建src/format/string.ts文件来导出驼峰命名函数

// base/src/format/string.ts

const camelizeRE = /-(\w)/g

/**
 *
 * @description 把-换成驼峰命名
 * @export camelize
 * @param {string} str
 * @return {*}  {string}
 */
export function camelize (str: string): string {
  return str.replace(camelizeRE, (_, c) => c.toUpperCase())
}
// base/src/create/component.ts
import { camelize } from '../format/string'
// 修改这句代码来转换为驼峰命名法
app.component(camelize(`-${name}`), sfc)

创建create/bem.ts文件生成bem的函数

Bem 函数传入参数与生成的名字

  • b() // 'button'
  • b('text') // 'button__text'
  • b({ disabled }) // 'button button--disabled'
  • b('text', { disabled }) // 'button__text button__text--disabled'
  • b(['disabled', 'primary']) // 'button button--disabled button--primary'
export type Mod = string | { [key: string]: any };
export type Mods = Mod | Mod[];

function gen (name: string, mods?: Mods): string {
  if (!mods) {
    return ''
  }

  if (typeof mods === 'string') {
    return ` ${name}--${mods}`
  }

  if (Array.isArray(mods)) {
    return mods.reduce<string>((ret, item) => ret + gen(name, item), '')
  }

  return Object.keys(mods).reduce(
    (ret, key) => ret + (mods[key] ? gen(name, key) : ''),
    ''
  )
}

/**
 *
 * @description 创建BEM命名空
 * @export
 * @param {string} name
 * @return {*} string
 */
export function createBEM (name: string) {
  return function (el?: Mods, mods?: Mods): Mods {
    if (el && typeof el !== 'string') {
      mods = el
      el = ''
    }

    el = el ? `${name}__${el}` : name

    return `${el}${gen(el, mods)}`
  }
}

export type BEM = ReturnType<typeof createBEM>;

创建create/index.ts文件,这个文件导出一个函数这个函数有一个参数,这个参数就是创建组件的名字,返回一个数组,这个数组的第一项是创建组件的方法,第二项就是根据组件名字创建bem命名规则的函数

import { createBEM } from './bem'
import { createComponent } from './component'

/**
 *
 *  @description 创建命名空间
 * @export
 * @param {string} name
 * @return {*} [createComponent(name), createBEM(name)]
 */
export function createNamespace (name: string) {
  name = 'two-' + name
  return [createComponent(name), createBEM(name)] as const
}

后续的公共的东西也会提取到公共base模块中