vue 封装 轮播组件 并发布到 npm 上

一、封装轮播组件

1. 首先来捋一下大概的思路

  • 组成部分大概有: 最外层盒子包裹, 需要轮播的部分, 指示器 和 左右两边的方向指示器
  • 需要设置的属性以及默认值:
    Property Deacription type default
    autoplay 是否开启自动播放 Boolean true
    duration 滑动间隔时长 Number 3000
    instial 默认显示第几项(下标) Number 0
    hasDot 是否显示指示器 Boolean true
    hasDirector 是否显示方向指示器 Boolean true
    dotBgColor 指示器背景色 String #ff5000
    dirBgColor 方向指示器颜色 String #fff

2. 创建项目以及对应文件

  • 首选创建一个最简化的 vue2.0 项目, 项目创建这边就不进行细述了
  • 项目创建完成, 在 src 目录下创建目录以及文件, index.js文件时入口文件, Carousel 目录中存放的则是轮播图的各个模块
    image.png

3. 进行代码编写 (整个编写流程, 这边不太好讲解, 所以只能把对应文件的 所有代码贴出)

  • 编写最外层盒子, 在 Carousel 目录下新建 index.vue 文件
<template>
  <div
    class="carousel"
    @mouseenter="mouseEnter"
    @mouseleave="mouseLeave"
  >
    <div class="inner">
      <slot></slot>
    </div>

    <!-- 指示器 -->
    <DotCar
      :currentIndex="currentIndex"
      :itemLen="itemLen"
      :hasDot="hasDot"
      :dotBgColor="dotBgColor"
      @dotClick="dotClick"
    />

    <!-- 两个方向指示器 -->
    <DriCar 
      v-if="hasDirector"
      dir="next"
      @dirClick="dirClick"
      class="dri-next"
      :dirBgColor="dirBgColor"
    />
    <DriCar 
      v-if="hasDirector"
      dir="prev"
      @dirClick="dirClick"
      class="dri-prev"
      :dirBgColor="dirBgColor"
    />

  </div>
</template>

<script>

import DotCar from './Dot.vue'
import DriCar from './Driector.vue'

export default {
  name: 'Carousel',
  components: {
    DotCar,
    DriCar
  },

  props: {

    // 是否自动播放
    autoplay: {
      type: Boolean,
      default: true
    },
    // 切换时长
    duration: {
      type: Number,
      default: 6000
    },
    // 默认显示哪一项
    instial: {
      type: Number,
      default: 0
    },
    // 是否展示指示器
    hasDot: {
      type: Boolean,
      default: true
    },
    // 是否展示方向按钮
    hasDirector: {
      type: Boolean,
      default: true
    },
    // 指示器背景色
    dotBgColor: String,

    // 方向指示器的颜色
    dirBgColor: String

  },

  data() {
    return{
      currentIndex: this.instial,
      time: null, // 定义一个计时器
      itemLen: 0, // 轮播的数组长度
    }
  },
  methods: {

    // 自动轮播的方法
    autoPlayFn() {
      if(this.autoplay) {
        this.time = setInterval(() => {
          this.setIndexFn('next')
        }, this.duration)

      }
    },

    // 处理轮播的方向 和 
    // dir 表示轮播的方向
    setIndexFn(dir) {
      switch(dir) {
        case 'next':
          this.currentIndex +=1;
          if(this.currentIndex === this.itemLen) {
            this.currentIndex = 0
          }
          break;
        case 'prev':
          this.currentIndex -=1;
          if(this.currentIndex === -1) {
            this.currentIndex = this.itemLen - 1
          }
          break;
      }

    },

    // 选中指示器, 修改展示下标为当前下标
    dotClick(index) {
      this.currentIndex = index
    },

    // 鼠标移入事件
    mouseEnter() {
      this.clearInter()
    },

    // 鼠标移出事件
    mouseLeave() {
      this.autoPlayFn()
    },


    // 左右指示器点击事件
    dirClick(val) {
      this.setIndexFn(val)
    },  

    //清除定时器
    clearInter() {
      clearInterval(this.time);
      this.time = null
    } 
  },

  // 执行自动播放
  mounted() {

    // 通过 this.$slots 获取到子组件的长度( 也就是遍历了多少项(轮播有多少项))
    this.itemLen = this.$slots.default.length

    this.autoPlayFn()
  },

  // 清除定时器, 并置空 time
  beforeDestroy() {
    this.clearInter()
  }

}
</script>

<style scoped>

  .carousel{
    position: relative;
    width: 100%;
    height: 100%;
  }

  .inner{
    width: 100%;
    height: 100%;
    overflow: hidden;
    } 

  .dri-next{
    left: 0;
  }

  .dri-prev{
    right: 0;
  }
</style>
  • 编写需要轮播的选项, 在 Carousel 目录下新建 Item.vue 文件
<template>

  <!-- 利用 transition 标签来完成动画的过渡 -->
  <transition>
    <div class="car-item" v-if="selfIndex === currentIndex">
      <slot></slot>
    </div>

  </transition>

</template>

<script>
export default {
  name: 'CarItem',

  data() {
    return{
      selfIndex: '',
      currentIndex:''
    }
  },

  mounted() {

    // 在 this.$parent 中 可以直接获取到上一级的 props 中所有属性
    // this._self 获取当前实例
    this.selfIndex = this._self.$vnode.key
    this.currentIndex = this.$parent.currentIndex

  },

  // 监听下标的变化 (监听  this.$parent.currentIndex)
  watch: {
    '$parent.currentIndex': function (val, oldVal) {
      this.currentIndex = val
     }

  }

}
</script>

<style scoped>

  .car-item{
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
  }



.v-enter-active,
.v-leave-active {
  /* 所有样式在 0.3s 的时候, 执行 linear 动画
    linear 表示动画从头到尾的速度是相同的
  */
  transition: all .3s linear;
}



/* 进入 */
.v-enter-active {
  transition: translateX(100%);
}

.v-enter-to{
  transition: translateX(0);
}



 /* 离开 */
.v-leave-active{
  transition: translateX(0);
}

.v-leave-to {
  transition: translateX(-100%);
}


</style>
  • 在入口文件 index.js 中注册
import Vue from 'vue';
import Carousel from './Carousel/index.vue';
import CarIterm from './Carousel/Item.vue';


let JscyUI = {}


// 全局注册组件
JscyUI.install = ((Vue) => {

   // Vue.component('组件name', 组件本身)
  Vue.component(Carousel.name, Carousel);

  Vue.component(CarIterm.name, CarIterm)

})



// 将组件暴露
export default JscyUI;

4. 这边可以先对写好的组件, 进行简单的使用

  • main.js 中引入
    main.js文件
  • 在 app.vue页面中直接使用 ( 使用时需要注意的是:要给包裹轮播组件的 div 设置宽高, 否则显示不出来 )


    image.png

    !!! 在这里呢, 一个大概的轮播已经成型, 下面我们可以看着页面来编写剩下的两个块指示器部分

5. 指示器的编写

  • 新建 Dot.vue 文件, 编写底部指示器
<template>
  <div class="dot-wrapper">
    <div 
      class="dot-item"
      v-for="item in itemLen"
      :key="item"
    >
      <a 
        class="dot-link"
        href="javascript:;"
        :style="{backgroundColor: (item - 1) === currentIndex ? dotBgColor : '#fff'}"
        @click="chooseCurrent(item - 1)"
        ></a>
    </div>
  </div>
</template>

<script>
export default {
  name: 'Dot',
  props: {
    itemLen: Number, // 轮播的张数
    currentIndex: Number, // 当前下标
    // 是否展示 指示器
    hasDot: {
      type: Boolean,
      default: true
    },
    // 指示器背景颜色
    dotBgColor: {
      type: String,
      default: '#ff5000'
    }
  },
  methods: {

    // 指示器点击事件
    chooseCurrent(index) {
      // console.log('点击')
      this.$emit('dotClick', index)
    }


  }



}
</script>

<style scoped>

  .dot-wrapper{
    width: 100%;
    height: 20px;
    position: absolute;
    bottom: 0;
    display: flex;
    justify-content: center;
    align-items: center;
  }

  .dot-item{
    margin: 2px;
  }

  .dot-item .dot-link{
    display: block;
    width: 8px;
    height: 8px;
    border-radius: 8px;
  }

</style>
  • 新建 Driector.vue 文件, 编写左右两侧方向指示器
<template>
  <div class="driector">
    <div v-if="dir === 'prev'">
      <a
        href="javascript:;"
        @click="dirClick('prev')"
        class="link-dir iconfont icon-the_next_step"
        :style="{color: dirBgColor}"
      ></a>
    </div>
    <div v-if="dir === 'next'">
      <a
        href="javascript:;"
        @click="dirClick('next')"
        class="link-dir iconfont icon-the_previous_step"
        :style="{color: dirBgColor}"
        ></a>
    </div>
  </div>
</template>

<script>
export default {
  name: 'Driector',
  props: {
    dir: String,
    dirBgColor: {
      type: String,
      default: '#fff'
    }
  },
  methods: {

    dirClick(val) {
      this.$emit('dirClick', val)
    }

  }
}
</script>

<style scoped>
@import url('./iconfont/iconfont.css');

.driector{
  position: absolute;
  top: 0;
  width: 20px;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 0 5px;
}

.link-dir{
  text-decoration: none;
  font-size: 18px;
}

</style>
  • 到这里两块指示器已经编写完成, 具体用法, 直接参考上面 inde.vue 文件, 其实写到这里, 整个轮播组件也已经编写完成
    轮播组件效果截图
二、如何发布到 npm 上

1. 准备好需要发布的文件

  • 在最外层 package.json 中进行打包配置
    package.json
    "package": "vue-cli-service build --target lib ./src/libs/jscy-ui/index.js --dest carouselSlide --name carousel"
  • 执行 npm run package 进行打包, 生成 carouselSlide 目录
    image.png
  • 新建 package 目录
    • carouselSlide 目录中的 carousel.umd.min.js 复制到 package 目录下
  • carouselSlide 目录中的 .css 样式文件 复制到 package 目录下
  • 初始化package目录, npm init -y 生成 package.json 文件
  • 配置 package.json 文件(我这边只做了简单配置)
    image.png

2. 对 npm 进行操作

  • 首先进到 npm 首页 , 在进行登录, 如果刚注册的, 注意一定要进行邮箱激活
  • 使用 nrm ls 查看当前源是否是 npm 官方源, 不是则需要切回
    • 没有 nrm , 使用 npm i nrm -g 进行安装
    • 使用 nrm use npm 切回到 npm 官方源
      image.png
  • 在终端登录 npm
    • 执行 npm login

    • 输入账号密码邮箱进行登录
      image.png
    • 执行 npm publish 进行发布

      image.png

  • 到此时已经发布成功, 刷新 npm 就可以看到


    image.png
三、组件的使用
!!! 到这里, 这篇文章就结束啦, 有问题的地方, 希望大家能够指出。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,193评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,306评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,130评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,110评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,118评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,085评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,007评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,844评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,283评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,508评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,667评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,395评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,985评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,630评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,797评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,653评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,553评论 2 352

推荐阅读更多精彩内容