记录一下vue3+typescript开发公共组件的注意事项
我的项目构造
|-- examples 搁置用于测试组件的代码| |-- App.vue| |-- main.ts|-- packages 搁置组件的代码| |-- index.ts| |-- shims-vue.d.ts| |-- assets| | |-- logo.png| |-- components| |-- helloWorld| |-- HelloWorld.tsx 组件的定义| |-- index.ts 组件裸露以及全局申明|-- public| |-- favicon.ico| |-- index.html|-- tests| |-- unit| |-- example.spec.ts|-- .browserslistrc|-- .eslintrc.js|-- .gitignore|-- babel.config.js|-- jest.config.js|-- package-lock.json|-- package.json|-- README.md|-- tsconfig.json|-- vue.config.js
组件编写
组件定义
// packages/components/helloWorld/HelloWorld.tsximport { defineComponent, type ExtractPropTypes } from "vue";const props = { /** 姓名 */ name: String, /** 年龄 */ age: Number,};// ExtractPropTypes:承受一个类型,返回vue3解决后的类型export type HelloWorldProps = ExtractPropTypes<typeof props>;export default defineComponent({ name: "HelloWorld", props: props, emits: ["click"], setup(props, { emit }) { const onClick = (event: MouseEvent) => { emit("click", event); }; return () => { return ( <tag> <div onClick={onClick}> HelloWorld, {props.name}, {props.age} </div> </tag> ); }; },});
组件申明,裸露
// packages/components/helloWorld/index.tsimport HelloWorld from "./HelloWorld";export { type HelloWorldProps } from "./HelloWorld";export default HelloWorld;// 组件调用时,提供代码提醒declare module "vue" { export interface GlobalComponents { HelloWorld: typeof HelloWorld; }}
组件注册
// packages/index.tsimport type { App } from "vue";import HelloWorld from "./components/helloWorld";// 定义install办法,供内部调用const install = (Vue: App) => { Vue.component("HelloWorld", HelloWorld);};export default { install };
编译插件
npm i -D vue-ts
配置文件
package.json
"scripts": { "lib": "vue-cli-service build --target lib --name xxx --dest lib packages/index.ts && vue-tsc --declaration --emitDeclarationOnly",}
tsconfig.json
{ "compilerOptions": { "outDir": "lib/types", // 指定编译后的文件门路 "target": "esnext", "module": "CommonJS", "strict": true, "jsx": "preserve", "moduleResolution": "node", "skipLibCheck": true, "esModuleInterop": true, "allowSyntheticDefaultImports": true, "forceConsistentCasingInFileNames": true, "useDefineForClassFields": true, "sourceMap": true, "baseUrl": ".", "types": [ "webpack-env", "jest" ], "paths": { "@/*": [ "packages/*" ] }, "lib": [ "esnext", "dom", "dom.iterable", "scripthost" ] }, "include": [ "packages/**/*.ts", "packages/**/*.tsx" ], "exclude": [ "node_modules" ]}