vite +ts+ vue封装一个组件并发布到npm

1.创建vue项目

npm create vite@latest vue3-plugin-test

2.在src 目录下创建plugins/Button.vue


<template>
  <button class="btn">
    <span>
      <!-- 自定义插槽 -->
      <slot></slot>
    </span>
  </button>
</template>
<script setup>
</script>
 
<script>
export default {
  //一定要写组件名
  name: "vue-button",
};
</script>
 
<style scoped>
.btn {
  display: inline-block;
  border-radius: 20px;
  background-color: #f4511e;
  border: none;
  color: #ffff;
  text-align: center;
  font-size: 28px;
  font-weight: 400;
  padding: 18px;
  width: 200px;
  transition: all 0.5s;
  cursor: pointer;
  margin: 5px;
  vertical-align: middle;
}

.btn span {
  cursor: pointer;
  display: inline-block;
  position: relative;
  transition: 0.5s;
}

.btn span::after {
  content: ">";
  position: absolute;
  opacity: 0;
  top: 0;
  right: -20px;
  transition: 0.5s;
}

.btn:hover span {
  padding-right: 30px;
}

.btn:hover span::after {
  opacity: 1;
  right: 0;
}
</style>

3.在src 目录下创建plugins/index.ts

const requireComponent = import.meta.glob("./*.vue", { eager: true });
let typeList: any = {};
const install: any = (Vue: any) => {
  if (install.installed) return;
  install.installed;

  Object.keys(requireComponent).forEach((fileName) => {
    //第i个组件
    const config: any = requireComponent[fileName];
    //组件名 刚才写的组件名派上用场了
    const conponentName = config.default.name;
    typeList[conponentName] = typeof conponentName;
    Vue.component(conponentName, config.default || config);
  });
  //这里也可以创建全局自定义指令 这里是创建了一个自动获取焦点的指令
  Vue.directive("focus", {
    mounted: function (el: any) {
      el.focus();
    },
  });
};

const vue = (window as any).Vue;
//环境检测
if (typeof window !== "undefined" && vue) {
  install(vue);
}
//对外暴露install方法
export default {
  install,
};
declare module "vue" {
  export interface GlobalComponents {}
}

4. 创建 Plugins/Msg.vue

<template>
  <div class="msg" ref="msg" :class="{ active: msgStatus }">

    <div class="msg-warpper"  :class="typeName">
      {{text}}
    </div>
  </div>
</template>
<script setup>
import { ref } from "vue";
//控制组件的显示
let msgStatus = ref(false);
let text = ref("");
let typeName=ref('')
const msgPlugin = function (msg, type = '', time = 2000) {

  text.value = msg;
  msgStatus.value = true;
  typeName.value = type;

  setTimeout(() => {
    msgStatus.value = false;
  }, time);
};
defineExpose({
  //向外暴露方法
  msgPlugin,
});
</script>
 
<script>
export default {
  name: "vue-msg",
};
</script>
 
<style scoped>
.msg {
  height: 22px;
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  width: 0;
  min-height: 0;
  text-align: center;
  background-color: rgba(0, 0, 0, 0.5);
  border-radius: 5px;
  color: #fff;
  transition: all 0.5s;
  z-index: -1;
  opacity: 0;
  
}
.error{
    background: red;
    width: 100%;
    height: 100%;
  }
.msg.active {
  width: 150px;
  min-height: 25px;
  opacity: 1;
  z-index: 11;
}
</style>

5 main.ts测试是否可以

import { createApp } from "vue";
import "./style.css";
import App from "./App.vue";
import myPlugin from "./packages/index";、
import vueMsg from "./plugins/index.ts";



createApp(App).use(vueMsg).mount("#app");

6. APP.VUE测试是否可以

<script setup lang="ts">
import { nextTick, ref } from "vue";
import HelloWorld from "./components/HelloWorld.vue";
let msg = ref();
let text = ref("");
function submit() {
  if (text.value !== "") {
    nextTick(() => {
      msg.value.msgPlugin("提交成功", 1000);
    });
  } else {
    nextTick(() => {
      msg.value.msgPlugin("输入不能为空",'error', 1000);
    });
  }
}
</script>
<template>
  <HelloWorld msg="sdfsd" />
  <input v-model="text" type="text" v-focus />
  <vue-button @click="submit">123</vue-button>
  <vue-msg ref="msg"></vue-msg>
</template>

<style scoped>
.logo {
  height: 6em;
  padding: 1.5em;
  will-change: filter;
  transition: filter 300ms;
}
.logo:hover {
  filter: drop-shadow(0 0 2em #646cffaa);
}
.logo.vue:hover {
  filter: drop-shadow(0 0 2em #42b883aa);
}
</style>

7.打包 配置 ,修改vite.config.ts

  build: {
    outDir: "lib", //输出文件名称
    lib: {
      entry: path.resolve(__dirname, "./src/plugins/index.ts"), //指定组件编译入口文件
      name: "vue-msg",
      fileName: "vue-msg",
    }, //库编译模式配置
    rollupOptions: {
      // 确保外部化处理那些你不想打包进库的依赖
      external: ["vue"],
      output: {
        // 在 UMD 构建模式下为这些外部化的依赖提供一个全局变量
        globals: {
          vue: "Vue",
        },
      },
    }, // rollup打包配置
  },

9. npm run build 打包成后会生成一个lib文件夹 然后 npm init -y 生成一个配置文件,修改配置文件

{
"name": "nancy-vue-msg",
"version": "1.0.1",
"description": "",
"main": "vue-msg.js",
"scripts": {
 "test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "nancy",
"license": "ISC"
}

10.npm login ,npm publish

11.npm i nancy-vue-msg 修改main.ts

import { createApp } from "vue";
import "./style.css";
import App from "./App.vue";
// import myPlugin from "./packages/index";
import vueMsg from "nancy-vue-msg";
import "../node_modules/nancy-vue-msg/style.css";
// import vueMsg from "./plugins/index.ts";

createApp(App).use(vueMsg).mount("#app");

如果报ts错误请添加 global.d.ts declare module "nancy-vue-msg";

需要代码请留言

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容