如何封装自定义组件库且跟第三方组件库一样在模板有类型提示呢?

1,016 阅读2分钟

封装自定义组件库:vue3

  • 思考:如何封装一个像element-ui的组件库?

  • 怎么直接在main.js入口文件use该第三方组件库,全局引入或者按需加载,就可以使用到该组件库的组件呢?并且在模板内有相应的代码提示呢?

1. 首先我们解决第一个问题:use注册组件库、全局引入和按需引入

  • 我们先来看element-ui如何使用的
// 全局引入
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
// 注册
Vue.use(ElementUI);

// 按需引入
// 第三包组件库按需引入
// 第一步是安装相关的插件,在babel.config.js配置相关信息,可以自行往官网查看文档
// 第二部按需引入组件
import { Button, Select } from 'element-ui';
// 第三步全局注册组件
Vue.component(Button.name, Button);
Vue.component(Select.name, Select);
  • 接下来先来说明全局引入

  • 首先先自己创建一个自定义button组件(components/UI/Button/index.vue)

    <template>
      <button class="xtx-button ellipsis" :class="[size, type]">
        <slot></slot>
      </button>
    </template>
    
    <script setup lang="ts">
    import type { PropType } from 'vue';
    
    defineProps({
      // 控制按钮大小 size: large middle small mini
      size: {
        type: String as PropType<'large' | 'middle' | 'small' | 'mini'>,
        default: 'middle',
      },
      // 控制按钮类型 type: primary plain gray
      type: {
        type: String as PropType<'primary' | 'plain' | 'gray'>,
        default: 'default',
      },
    });
    </script>
    
    <style scoped lang="less">
    // 基于类名定义一些和定制样式无关的样式
    .xtx-button {
      appearance: none;
      border: none;
      outline: none;
      background: #fff;
      text-align: center;
      border: 1px solid transparent;
      border-radius: 4px;
      cursor: pointer;
    }
    // 大
    .large {
      width: 240px;
      height: 50px;
      font-size: 16px;
    }
    // 中
    .middle {
      width: 180px;
      height: 50px;
      font-size: 16px;
    }
    // 小
    .small {
      width: 100px;
      height: 32px;
    }
    //超小
    .mini {
      width: 60px;
      height: 32px;
    }
    .default {
      border-color: #e4e4e4;
      color: #666;
    }
    // 确认
    .primary {
      border-color: @xtxColor;
      background: @xtxColor;
      color: #fff;
    }
    // 普通
    .plain {
      border-color: @xtxColor;
      color: @xtxColor;
      background: lighten(@xtxColor, 50%);
    }
    // 灰色
    .gray {
      border-color: #ccc;
      background: #ccc;
      color: #fff;
    }
    </style>
    
    
  • 第二步,components/UI文件夹下新建index.ts文件

    // 以Button组件为例子
    import Button from './Button/index.vue';
    
    // 按需导出组件
    export const XtxButton = Button;
    
    // 封装成插件形式
    export default {
        insatll(app:APP){
            // 全局注册
             app.component('XtxButton', Button);
        }
    }
    
  • 封装组件和按需导出组件、插件形式导出组件完成

    // main.ts
    import { createApp } from 'vue';
    import App from '@/App.vue';
    
    // 自定义组件库
    import XtxUI from './components/XtxUI';
    
    // 按需导入Button
    import {BUtton} from './components/XtxUI'
    
    const app = createApp(App);
    
    // 注册全局组件库,Plugin插件,use了就会立即执行install方法
    app.use(XtxUI)
    
    // 按需导入自然也是可以的
    app.component('MyButton',Button)
    
    app.mount('#app');
    
  • 以上完成了导入导出功能。最后还差一步,怎么实现在组件内使用组件有类型提示呢?

  • 答案是:为自定义组件库声明类型提示

  • 在components/UI文件夹下新建 components.d.ts类型声明文件

  • 注意:.d.ts文件仅仅是提供类型声明,并不会编译成js代码

  • // 以Button组件为例
    import Button from './Button/index.vue';
    // 给Volar去识别
    declare module 'vue' {
      // 全局组件需通过 GlobalComponents 接口定义(Volar文档中说明)
      export interface GlobalComponents {
        // vue-router 的两个全局组件,添加类型声明
        RouterLink: typeof import('vue-router')['RouterLink'];
        RouterView: typeof import('vue-router')['RouterView'];
          // 自己的全局组件注册类型声明, typeof 表示基于获取组件的TS类型
        MyButton: typeof Button;
      }
    
  • 声明类型文件之后,在组件内我们就可以使用到跟第三方组件库一样的类型提示啦!