vue3+typescript开发公共组件

记录一下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.tsx
import { 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.ts
import HelloWorld from "./HelloWorld";
export { type HelloWorldProps } from "./HelloWorld";
export default HelloWorld;

// 组件调用时,提供代码提示
declare module "vue" {
  export interface GlobalComponents {
    HelloWorld: typeof HelloWorld;
  }
}

组件注册

// packages/index.ts
import 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"
  ]
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值