沉淀自己的pro-table组件,并发布到npm(Vue3、element-plus)

文章目录

    • 沉淀自己的pro-table组件,并发布到npm
      • Quick Start
      • 开发过程笔记
      • add TS Support
    • 参考资料

沉淀自己的pro-table组件,并发布到npm

传送门

约定:npm包名vue3-el-pro-table,引用vue3-el-pro-table的包名为“本项目”。

声明:Vue3ProTable.vue代码是在这个项目的基础上进行修改的。

作者:hans774882968以及hans774882968以及hans774882968

Quick Start

yarn add vue3-el-pro-table

src/main.ts

import 'vue3-el-pro-table/dist/vue3-el-pro-table.css';
import Vue3ProTable from 'vue3-el-pro-table';

createApp(App)
  .use(Vue3ProTable)
  .mount('#app');

Then use directly in .vue file.

Import interface:

import { Vue3ProTableProps } from 'vue3-el-pro-table';

Component props definition:

export declare interface Vue3ProTableProps {
  request: (...args: any[]) => Promise<{ data: object[], total: number }>
  // 表格标题
  title?: string
  // 是否隐藏标题栏
  hideTitleBar?: boolean
  // 搜索表单配置,false表示不显示搜索表单
  search?: boolean | object
  border?: boolean
  // 表头配置
  columns?: object[]
  // 行数据的Key,同elementUI的table组件的row-key
  rowKey?: string
  // 分页配置,false表示不显示分页
  pagination?: boolean | object
  tree?: object
  // The above attributes are all from https://github.com/huzhushan/vue3-pro-table. The following properties are added by me.
  loadTableDataBeforeMount?: boolean
  blockRedundantRequestOnReset?: boolean
  paddingLeft?: string | number
  paddingRight?: string | number
}

Plz refer to https://github.com/huzhushan/vue3-pro-table for instructions on how to use vue3-el-pro-table.

开发过程笔记

根据参考链接3,实际上我们只需要提供一个符合Vue插件格式的入口install.js,和一个Vue组件。但为了满足npm包迭代过程中的预览、测试等需求,我们仍然需要以组件库的标准来开发这个npm包。因此我采用的方案是:先使用vue-cli快速创建一个项目,满足组件的预览、测试等需求,在此基础上再新增一个构建流程。

  1. 使用vue-cli创建一个普通的Vue3 + TS项目。
  2. 新增组件src/components/Vue3ProTable.vue
  3. 新增Vue插件入口src/install.js
import HelloWorld from './components/HelloWorld.vue';
import Vue3ProTable from './components/Vue3ProTable.vue';

function install(app) {
  if (install.installed) return;
  install.installed = true;

  app.component('test-hello-world', HelloWorld); // 顺便把脚手架生成的组件也注册为全局组件
  app.component('vue3-pro-table', Vue3ProTable);
}

Vue3ProTable.install = install;

export default { install };
  1. 新增build-lib命令并运行yarn build-lib——这就是vue3-el-pro-table生成Vue插件的构建命令:
{
  "scripts": {
    "build": "vue-cli-service build", // 作为对比
    "build-lib": "vue-cli-service build --target lib --name vue3-el-pro-table ./src/install.js" // 参考:https://cli.vuejs.org/guide/build-targets.html#library
  },
}
  1. 构建成功后修改package.json修改下入口:
{
  "main": "dist/vue3-el-pro-table.umd.js",
}

在另一个项目(即本项目)预览最新改动:

yarn add file:../vue3-el-pro-table

接下来开始踩坑了。当引入的组件使用slot的时候会报错:

Cannot read properties of null (reading 'isCE')

根据参考链接2,原因是本项目和vue3-el-pro-table各有一个vue,即使它们版本相同也会引起冲突。虽然参考链接2的提问说给webpack添加vue配置无济于事,但我的项目用这个配置是可以解决问题的。

在本项目的vue.config.js禁用symlinks并alias vue:

const { defineConfig } = require('@vue/cli-service');
const path = require('path');

module.exports = defineConfig({
  chainWebpack(config) {
    config.resolve.symlinks(false);
    config.resolve.alias.set('vue', path.resolve('./node_modules/vue'));
  },
  devServer: {
    port: 8090,
  },
  transpileDependencies: true,
});

add TS Support

为了防止本项目报TS错误,我们的npm包vue3-el-pro-table需要给出.d.ts文件。

  1. 本项目package.json指定类型定义文件路径:
{
  "types": "dist/global.d.ts"
}
  1. 本项目tsconfig.json新增配置:
{
  "compilerOptions": {
    "types": [
      "webpack-env",
      "jest",
      "vue3-el-pro-table/dist/global.d.ts", // 获取 vue3-el-pro-table 注册的全局组件的类型提示
      "element-plus/global.d.ts" // 获取 element-plus 组件的类型提示
    ],
  }
}

global.d.ts不应该放在dist目录,因此我把它放到了src/global.d.ts,并配置CopyWebpackPluginvue3-el-pro-tablevue.config.js

const { defineConfig } = require('@vue/cli-service');
const path = require('path');
const CopyWebpackPlugin = require('copy-webpack-plugin');

module.exports = defineConfig({
  configureWebpack: {
    plugins: [
      new CopyWebpackPlugin({
        patterns: [
          {
            from: path.resolve(__dirname, 'src', 'global.d.ts'),
            to: path.resolve(__dirname, 'dist'),
          },
        ],
      }),
    ],
  },
  transpileDependencies: true,
});

最理想的情况下dist/global.d.ts能在编译时直接生成,但可惜我们参考的Vue3ProTable.vue不是一个TS组件,且改造为TS组件的工作量过大,因此global.d.ts是手动维护的,传送门。

我们期望dist/global.d.ts能够给组件提供类型提示。根据参考链接4,需要以下代码:

declare const CVue3ProTable: import('vue').DefineComponent<......>;
declare const CHelloWorld: import('vue').DefineComponent<{
  msg: StringConstructor;
}, unknown, unknown, object, object, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, object, string, import('vue').VNodeProps & import('vue').AllowedComponentProps & import('vue').ComponentCustomProps, Readonly<import('vue').ExtractPropTypes<{
  msg: StringConstructor;
}>>, object, object>;

declare module 'vue' {
  export interface GlobalComponents {
    Vue3ProTable: typeof CVue3ProTable
    TestHelloWorld: typeof CHelloWorld
  }
}

这里的CVue3ProTable, CHelloWorld看上去很复杂,不会是手写的吧?的确不是手写的,可以让vue-tsc生成。首先安装vue-tsc并新增命令:

{
  "gen-declaration": "vue-tsc -p tsconfig.declaration.json"
}

然后新增tsconfig.declaration.json

{
  "extends": "./tsconfig.json",
  "compilerOptions": {
    "outDir": "es",
    "declaration": true,
    "emitDeclarationOnly": true
  },
  "include": ["src"],
  "exclude": ["node_modules", "**/__tests__/**", "**/__demos__/**", "**/*.md"]
}

最后执行yarn gen-declaration,把组件的类型定义复制到global.d.ts即可。

参考资料

  1. 声明式 UI 介绍:https://flutter.cn/docs/get-started/flutter-for/declarative
  2. Cannot read properties of null (reading ‘isCE’):https://stackoverflow.com/questions/71063992/when-importing-self-made-vue-3-library-into-vue-3-project-uncaught-typeerror
  3. 在 NPM 上创建并发布您的第一个 Vue.JS 插件:https://5balloons.info/create-publish-you-first-vue-plugin-on-npm-the-right-way/
  4. 全局组件类型声明的最佳实践 (Vue3+TS+Volar):https://juejin.cn/post/7066730414626308103

你可能感兴趣的:(vue,web&CTF,前端,vue.js,typescript)