npm+vue-cli 公布 vue 自定义组件
日常开发中, 咱们常常会封装一些组件, 在多个我的项目切换组件的批改特地麻烦, 咱们能够把这些常常用到的组件公布到 npm 下面进行对立治理, 这样能够大大提高咱们的工作效率, 甚至到前期能够本人封装一套属于本人的组件库;
- 应用 vue-cli 疾速创立我的项目
-
components 目录中创立自定义组件; 上面以 vue-cricleprogressbar 组件为例 CircleProgress.vue
<template> <div class="content" ref="box"> <svg :id="idStr" style="transform: rotate(-90deg)" :width="width" :height="width" xmlns="http://www.w3.org/2000/svg" > <linearGradient :id="`gradient-${id}`" gradientUnits="userSpaceOnUse"> <stop v-for="(item, index) in gradientsColor" :key="index" :offset="item.offset" :stop-color="item.color" /> </linearGradient> <circle :r="(width-radius)/2" :cy="width/2" :cx="width/2" :stroke-width="radius" :stroke="backgroundColor" fill="none" /> <circle v-if="gradientsColorShow" ref="$bar" :r="(width-radius)/2" :cy="width/2" :cx="width/2" :stroke="gradientsColor ? `url(#gradient-${id})` : barColor" :stroke-width="radius" :stroke-linecap="isRound ?'round':'square'":stroke-dasharray="(width-radius)*3.14":stroke-dashoffset="dashoffsetValue"fill="none" /> </svg> <div class="center_text"> <p v-if="!$slots.default" class="title">{{progress}}%</p> <slot></slot> </div> </div> </template> <script> // import _ from "lodash"; export default { props: { widthPresent: { type: Number, default: 1 }, gradientsColor: {type: [Boolean, Array], default: false }, radius: {type: [Number, String], default: 20 }, // 进度条厚度 progress: {type: [Number, String], default: 20 }, // 进度条百分比 barColor: { type: String, default: "#1890ff" }, // 进度条色彩 backgroundColor: { type: String, default: "rgba(0,0,0,0.3)" }, // 背景色彩 isAnimation: { // 是否是动画成果 type: Boolean, default: true }, isRound: { // 是否是圆形画笔 type: Boolean, default: true }, id: { // 组件的 id,多组件共存时应用 type: [String, Number], default: 1 }, duration: { // 整个动画时长 type: [String, Number], default: 1000 }, delay: { // 提早多久执行 type: [String, Number], default: 200 }, timeFunction: { // 动画缓动函数 type: String, default: "cubic-bezier(0.99, 0.01, 0.22, 0.94)" } }, data() { return { width: 200, idStr: "", oldValue: 0 }; }, computed: {gradientsColorShow: function() {return true;}, dashoffsetValue: function() {const { isAnimation, width, radius, progress, oldValue} = this; return isAnimation ? ((width - radius) * 3.14 * (100 - oldValue)) / 100 : ((width - radius) * 3.14 * (100 - progress)) / 100; } }, watch: {id: function() {this.idStr = `circle_progress_keyframes_${this.id || 1}`; }, progress: function(newData, oldData) {if (newData !== oldData) { this.oldValue = oldData; this.setAnimation();} } }, mounted() {this.idStr = `circle_progress_keyframes_${this.id || 1}`; let self = this; this.setCircleWidth(); this.setAnimation(); // 此处不能应用 window.onresize window.addEventListener("resize", function() {self.setCircleWidth(); self.setAnimation(self); }); }, methods: {setCircleWidth() {const { widthPresent} = this; let box = this.$refs.box; let width = box.clientWidth * widthPresent; let height = box.clientHeight * widthPresent; let cW = width > height ? height : width; this.width = cW; }, setAnimation() { let self = this; if (self.isAnimation) { // 反复定义判断 if (document.getElementById(self.idStr)) {self.$refs.$bar.classList.remove(`circle_progress_bar${self.id}`); } this.$nextTick(() => {this.startAnimation(); }); } }, startAnimation() { // 生成动画款式文件 let style = document.createElement("style"); style.id = this.idStr; style.type = "text/css"; style.innerHTML = ` @keyframes circle_progress_keyframes_name_${this.id} {from {stroke-dashoffset: ${((this.width - this.radius) * 3.14 * (100 - this.oldValue)) / 100}px;} to {stroke-dashoffset: ${((this.width - this.radius) * 3.14 * (100 - this.progress)) / 100}px;}} .circle_progress_bar${this.id} {animation: circle_progress_keyframes_name_${this.id} ${this.duration}ms ${this.delay}ms ${this.timeFunction} forwards;}`; // 增加新款式文件 document.getElementsByTagName("head")[0].appendChild(style); // 往 svg 元素中增加动画 class this.$refs.$bar.classList.add(`circle_progress_bar${this.id}`); } } }; </script> <style scoped> .content { height: 100%; display: flex; justify-content: center; align-items: center; } .center_text { position: absolute; color: #1890ff; font-size: 22px; font-weight: bold; } </style>
-
在创立 src/index.js, 这里提供两种办法
// 办法一, 间接引入组件, 无奈全局注册 import CircleProgress from './components/CircleProgress.vue'; export default CircleProgress; // 办法二, 为组件提供 install 装置办法, 供按需引入 import CircleProgress from './components/CircleProgress.vue'; CircleProgress .install = function (Vue) {Vue.component(CircleProgress.name, CircleProgress) } export default CircleProgress
-
配置 package.json 文件
{ "name": "vue-circleprogressbar", // 组件名称 "version": "1.2.2", // 组件版本号 "private": false, "main": "lib/vue-circleprogressbar.umd.min.js", // 组件入口, 在 scripts.package 命令中生成 "scripts": { "serve": "vue-cli-service serve", "build": "vue-cli-service build", "lint": "vue-cli-service lint", "package": "vue-cli-service build --target lib --name vue-circleprogressbar --dest lib ./src/components/index.js", // 创立 lib 文件夹, 将打包好的组件导入文件夹中 }, "keywords": [], "author": [], "license": "MIT", "dependencies": {}, "devDependencies": {}}
到这里本地开发工作就根本实现了, 下一步就是把本地组件推送到 npm 下面
- 首先须要在 npm 创立一个账号
- 在终端执行 npm login 输出你注册的 npm 的账号和明码
- 执行 npm publish, 如果没问题的话这里组件就胜利上传到 npm 下面了
- 前面就能够像引入其余组件一样间接用 npm install 装置组件进行引入
不分明的能够参考我写的 vue-circleprogressbar 组件源码: vue-circleProgress 组件