文章目录
- 沉淀自己的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 | objectborder?: boolean// 表头配置columns?: object[]// 行数据的Key,同elementUI的table组件的row-keyrowKey?: string// 分页配置,false表示不显示分页pagination?: boolean | objecttree?: object// The above attributes are all from https://github.com/huzhushan/vue3-pro-table. The following properties are added by me.loadTableDataBeforeMount?: booleanblockRedundantRequestOnReset?: booleanpaddingLeft?: string | numberpaddingRight?: 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
快速创建一个项目,满足组件的预览、测试等需求,在此基础上再新增一个构建流程。
- 使用
vue-cli
创建一个普通的Vue3 + TS项目。 - 新增组件
src/components/Vue3ProTable.vue
。 - 新增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 };
- 新增
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},}
- 构建成功后修改
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
文件。
- 本项目
package.json
指定类型定义文件路径:
{"types": "dist/global.d.ts"}
- 本项目
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
,并配置CopyWebpackPlugin
。vue3-el-pro-table
的vue.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 CVue3ProTableTestHelloWorld: 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
即可。
参考资料
- 声明式 UI 介绍:https://flutter.cn/docs/get-started/flutter-for/declarative
- 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
- 在 NPM 上创建并发布您的第一个 Vue.JS 插件:https://5balloons.info/create-publish-you-first-vue-plugin-on-npm-the-right-way/
- 全局组件类型声明的最佳实践 (Vue3+TS+Volar):https://juejin.cn/post/7066730414626308103