npm+vue-cli发布vue自定义组件

cgd199158

npm+vue-cli发布vue自定义组件

日常开发中,我们经常会封装一些组件,在多个项目切换组件的修改特别麻烦,我们可以把这些经常用到的组件发布到npm上面进行统一管理,这样可以大大提高我们的工作效率,甚至到后期可以自己封装一套属于自己的组件库;
  1. 使用vue-cli快速创建项目
  2. 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>
    
  3. 在创建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 
  4. 配置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上面

  5. 首先需要在 npm 创建一个账号
  6. 在终端执行 npm login 输入你注册的 npm 的账号和密码
  7. 执行npm publish,如果没问题的话这里组件就成功上传到npm上面了
  8. 后面就可以像引入其他组件一样直接用npm install安装组件进行引入

不清楚的可以参考我写的vue-circleprogressbar组件源码: vue-circleProgress组件

阅读 180

一个站在前端门口的门外汉!

52 声望
0 粉丝
0 条评论
你知道吗?

一个站在前端门口的门外汉!

52 声望
0 粉丝
宣传栏