文章目录
- 一、封装组件
- 1、创建组件项目
- 2、进入项目按照所需插件
- 3、运行项目
- 4、删除文件
- 5、修改App.vue
- 6、修改main.ts文件
- 7、新建组件目录
- fuyuComp/src/theme-chalk/fyCard.scss
- fuyuComp/src/theme-chalk/fyList.scss
- fuyuComp/src/theme-chalk/index.scss
- fuyuComp/packages/fyCard/index.vue
- fuyuComp/src/packages/fyCard/index.ts
- fuyuComp/src/packages/fyList/index.vue
- fuyuComp/src/packages/fyList/index.ts
- fuyuComp/src/packages/index.ts 导出所有组件
- fuyuComp/src/packages/index.d.ts
- fuyuComp/src/resolver.ts
- fuyuComp/vite.config.build.resolver.ts
- fuyuComp/vite.config.build.ts
- 修改【src/package.json】文件
- 8、打包
- 9、发布 npm
- 二、创建另一个工程,测试使用组件
- 三、关于组件内部使用其他组件插件,比如element-plus
- 四、git下载完整示例代码
一、封装组件
1、创建组件项目
npm create vite@latest
2、进入项目按照所需插件
cd fuyuComp
npm i
npm i sass -D
npm i unplugin-vue-components -D
npm i @types/node --D
npm i vite-plugin-dts -D
3、运行项目
npm run dev
4、删除文件
style.css
components
5、修改App.vue
<script setup lang="ts"></script>
<template>app.vue页面</template>
<style scoped></style>
6、修改main.ts文件
import { createApp } from “vue”;
import App from “./App.vue”;
const app = createApp(App);
app.mount(“#app”);
7、新建组件目录
fuyuComp/src/theme-chalk/fyCard.scss
.fy-card{
background-color:brown;
width: 500px;
padding: 20px;
color: #fff;
}
fuyuComp/src/theme-chalk/fyList.scss
.fy-list{
background-color: yellow;
width: 500px;
padding: 20px;
}
fuyuComp/src/theme-chalk/index.scss
@import "./fyCard.scss";
@import "./fyList.scss";
fuyuComp/packages/fyCard/index.vue
<template>
<div class="fy-card">
我是 fyCard 组件
</div>
</template>
<script lang="ts" setup></script>
<style lang="scss" scoped></style>
fuyuComp/src/packages/fyCard/index.ts
import fyCard from "./index.vue";
fyCard.install = function (app) {
app.component("fyCard", fyCard);
};
export { fyCard };
export default fyCard;
fuyuComp/src/packages/fyList/index.vue
<template>
<div class="fy-list">
我是 fyList 组件
</div>
</template>
<script lang="ts" setup></script>
<style lang="scss" scoped></style>
fuyuComp/src/packages/fyList/index.ts
import fyList from "./index.vue";
fyList.install = function (app) {
app.component("fyList", fyList);
};
export { fyList };
export default fyList;
fuyuComp/src/packages/index.ts 导出所有组件
import fyCard from "./fyCard/index";
import fyList from "./fyList/index";
import "../theme-chalk/index.scss";
const components = {
fyCard,
fyList,
};
const install = function (app) {
Object.keys(components).forEach((key) => {
app.component(key, components[key]);
});
};
export { fyCard, fyList };
export default {
install,
};
fuyuComp/src/packages/index.d.ts
fuyuComp/src/resolver.ts
import type {
ComponentResolveResult,
ComponentResolver,
} from "unplugin-vue-components/types";
function getIoResolved(name: string): ComponentResolveResult {
const packageName = "fuyu-comp";
const style = `${packageName}/dist/style.css`;
//因为name传入进来时首字母是大写的,但我们的组件首字母是小写的,所以需要对组件首字母大写转小写
const compName = name.replace(name[0], name[0].toLocaleLowerCase());
return {
name: compName,
from: packageName,
sideEffects: style,
};
}
const FuyuCompResolver = (): ComponentResolver => {
return {
type: "component",
resolve: (name) => {
//name就是组件的名称,name传入进来时,首字母默认就是大写的
if (name.startsWith("Fy")) {
//这里对是否为fy开头的组件做一个过滤处理
return getIoResolved(name);
}
},
};
};
export { FuyuCompResolver };
export default FuyuCompResolver;
fuyuComp/vite.config.build.resolver.ts
import { defineConfig } from "vite";
import path, { resolve } from "path";
import vue from "@vitejs/plugin-vue";
import dts from "vite-plugin-dts";
export default defineConfig({
resolve: {
alias: {
"@": resolve(__dirname, "./src"),
},
},
plugins: [
vue(),
dts(), //使用的typescript,需要生成*.d.ts声明文件
],
build: {
minify: true,
lib: {
entry: path.resolve(__dirname, "./src/resolver.ts"),
name: "name",
fileName: (format) => {
if (format === "es") {
return "resolver.mjs";
} else {
return "resolver.cjs";
}
},
formats: ["es", "cjs"],
},
rollupOptions: {
// 确保外部化处理那些你不想打包进库的依赖
external: ["vue"],
output: {
dir: path.resolve(__dirname, "./dist"),
},
},
emptyOutDir: false,
},
});
fuyuComp/vite.config.build.ts
import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
import { resolve } from "path";
import dts from "vite-plugin-dts";
// 打包后的目录
// https://vitejs.dev/config/
export default defineConfig({
resolve: {
alias: {
"@": resolve(__dirname, "./src"),
},
},
plugins: [
vue(),
dts(), //使用的typescript,需要生成*.d.ts声明文件
],
//配置打包入口 https://cn.vitejs.dev/guide/build.html#library-mode
build: {
lib: {
entry: resolve(__dirname, "./src/packages/index.ts"), //入口
name: "fuyu-comp", //组件名
fileName: (format) => `fuyu-comp.${format}.ts`,
},
rollupOptions: {
// 确保外部化处理那些你不想打包进库的依赖
external: ["vue"],
output: {
// 在 UMD 构建模式下为这些外部化的依赖提供一个全局变量
globals: {
vue: "Vue",
},
// dir: resolve(__dirname, 'dist') //打包输出目录
},
},
},
});
修改【src/package.json】文件
{
"name": "fuyu-comp",
"private": false,
"version": "0.0.1",
"files": [
"dist"
],
"type": "module",
"style": "./dist/style.css",
"main": "./dist/fuyu-comp.umd.ts",
"module": "./dist/fuyu-comp.es.ts",
"typings": "./dist/packages/index.d.ts",
"exports": {
".": {
"types": "./dist/packages/index.d.ts",
"import": "./dist/fuyu-comp.es.ts",
"require": "./dist/fuyu-comp.umd.ts"
},
"./resolver": {
"types": "./dist/resolver.d.ts",
"import": "./dist/resolver.mjs",
"require": "./dist/resolver.cjs"
},
"./*": [
"./*",
"./*.d.ts"
]
},
"typesVersions": {
"*": {
"*": [
"./dist/*",
"./*"
]
}
},
"scripts": {
"dev": "vite",
"build": "vite build && vite build --config vite.config.build.ts && vite build --config vite.config.build.resolver.ts ",
"preview": "vite preview"
},
"dependencies": {
"element-plus": "^2.3.14",
"vue": "^3.3.4"
},
"devDependencies": {
"@types/node": "^20.2.5",
"@vitejs/plugin-vue": "^4.2.3",
"sass": "^1.62.1",
"typescript": "^5.1.3",
"unplugin-vue-components": "^0.25.0",
"vite": "^4.3.9",
"vite-plugin-dts": "^3.5.3",
"vue-tsc": "^1.6.5"
},
"description": "### 安装 * npm install --save fuyu-comp",
"repository": {
"type": "git",
"url": "https://gitee.com/xxxxx/fuyu-comp.git"
},
"keywords": [
"fy"
],
"author": "fuyu",
"license": "ISC"
}
8、打包
npm run build
打包后生成目录如下图
9、发布 npm
- 登录:npm login
如果报错:npm ERR! Unexpected token < in JSON at position 0 while parsing near ‘<!DOCTYPE HTML PUBLI…’
依次输入:
npm config get registry
npm config set registry https://registr.npmjs.org 【切换为npm镜像】
npm login
如果还报错,依次输入:【这次报错应该是网络错误】
npm config get proxy
npm config get https-proxy
npm config set registry https://registry.npmjs.org
npm login- 输入账号:
- 输入:密码 【密码输入是看不见的,输入了就行】
- 输入邮箱:643164248@qq.com 【邮箱会收到验证码】
- 输入:验证码
- 发布:npm publish
二、创建另一个工程,测试使用组件
1、创建新的工程
npm init vite@latest useDemo --template vue
…此处省略创建步骤
2、安装组件插件
npm i fuyu-comp
3、注册组件插件的方式
(1)全局注册
【main.ts】全局注册组件
import fuyuComp from "fuyu-comp";
import "fuyu-comp/dist/style.css";
app.use(fuyuComp);
【xxx.vue】使用组件
<template>
<fyCard></fyCard>
<fyList></fyList>
</template>
(2)手动按需引入
【main.ts】全局引入样式
import "../theme-chalk/index.scss";
【xxx.vue】使用组件时再注册组件
<script setup lang="ts">
import { fyCard} from "fuyu-comp";
</script>
<template>
<fyCard></fyCard>
</template>
(3)使用插件 unplugin-vue-components 按需引入 推荐使用此方式!!!
安装
npm i unplugin-vue-components -D
【vite.config.ts】配置按需引入
(4)使用插件 unplugin-vue-components 按需引入 若组件内部没有配置resolver.ts的组件插件,可使用此方式
安装
npm i unplugin-vue-components -D
【vite.config.ts】配置按需引入
三、关于组件内部使用其他组件插件,比如element-plus
1、组件工程安装element-plugin,并进行全局注册。 不推荐此方式
此种方式在使用此插件时,只有进行全局注册,组件内部使用的element-plus的组件才会生效
手动按需引入、插件按需引入都不生效。
全局注册还会使得组件插件变大
所以不推荐使用此种方式!!!
(1)安装element-plus
npm i element-plugin
(2)全局注册 element-plus
在【fuyuComp/src/packages/index.ts】中加入代码
(3)在组件中使用element-plus
在【fuyuComp/src/packages/fyCard/index.vue】文件直接使用
(4)修改插件版本
在【fuyuComp/package.json】文件中修改插件版本
(5)打包发布至npm
npm run build
npm publish
2、组件工程安装element-plugin,并进行按需注册。简易版
此种方式在使用组件插件时无论是全局注册、还是手动按需、插件按需注册都生效。
(1)安装element-plus
npm i element-plugin
(2)全局引入element-plus 样式
在【fuyuComp/src/packages/index.ts】中加入代码
(3)在【fuyuComp/src/packages/fyCard/index.vue】文件引入使用
(4)修改插件版本
在【fuyuComp/package.json】文件中修改插件版本
(5)打包发布至npm
npm run build
npm publish
3、组件工程安装element-plugin,并进行按需注册。完善版 推荐使用!!!
(1)安装element-plus
npm i element-plugin
(2)新建在src文件下新建目录plugins存放第三方插件的按需引入
fuyuComp/src/plugins/elementPlus/index.ts
import "element-plus/dist/index.css";
import en from "element-plus/es/locale/lang/en";
const install = (app, opts = {}) => {
app.provide("$locale", opts.locale ? opts.locale : en);
};
export default {
install,
};
fuyuComp/src/plugins/index.ts
import elementPlus from "./elementPlus";
export default {
elementPlus,
};
(3)新建在src文件下新建组件fyConfigProvider存放国际化语言配置
fuyuComp/src/packages/fyConfigProvider/index.vue
<template>
<el-config-provider :locale="locale">
<slot></slot>
</el-config-provider>
</template>
<script lang="ts" setup>
import { ElConfigProvider } from "element-plus";
defineProps({
locale: {
//语言包
type: Object,
},
});
</script>
fuyuComp/src/packages/fyConfigProvider/index.ts
import fyConfigProvider from "./index.vue";
fyConfigProvider.install = function (app) {
app.component("fyConfigProvider", fyConfigProvider);
};
export { fyConfigProvider };
export default fyConfigProvider;
(4)在【fuyuComp/packages/index.ts】中加入代码,注册插件
(5)例如在fyCard组件中使用到国际化
(6)修改插件版本
在【fuyuComp/package.json】文件中修改插件版本
(7)打包发布至npm
npm run build
npm publish
(8)在另一个工程下载使用组件插件
npm i fuyu-comp
全局注册,配置国际化语言
【main.ts】
按需使用,配置国际化语言
在【vite.config.ts】配置,使用unplugin-vue-components按需引入组件插件
在【APP.vue】文件,使用fyConfigProvider组件来配置国际化语言
四、git下载完整示例代码
包含:组件插件工程fuyuComp、使用组件插件的工程useDemo
https://github.com/FuyuMiracle/npm-publish-comp-demo.git