基于 vue 写一个轮播组件

为什么要自己写一个轮播组件?

市面上用的最多的轮播组件无疑是 swiper 了,但是它真的太大了,大多数功能都用不到。

使用 [mint-ui] swiper 时我发现,当一个轮播未完成时无法继续滑动,需要等当前的轮播结束后才能继续滑动,使用 vant swiper 时我发现滑动效果不是很流畅。于是决定自己写一个 swiper。

  • github地址:yus-swipe
  • h5 体验地址:demo
  • scale effect 效果(类似于APP):demo

从体验上讲,我实现的这个比其他两者都要好,更接近swiper,喜欢的话点个star,同时也接受批评。

撸起袖子开始写

Props 定义

    // 轮播方向
    direction: {
      type: String,
      default: VERTICAL,
      validator: value => [VERTICAL, HORIZONTAL].indexOf(value) > -1
    },

    // 是否无限模式
    loop: {
      type: Boolean,
      default: false
    },

    // 轮播速度
    speed: {
      type: Number,
      default: 300
    },

    // 初始索引
    activeIndex: {
      type: Number,
      default: 0
    },

    // 是否自动轮播
    autoplay: {
      type: Boolean,
      default: false
    },

    // 轮播间隔
    delay: {
      type: Number,
      default: 4000
    },

    // 切换效果
    effect: {
      type: String,
      default: 'slide'
    }

data 定义

  data() {
    return {
      wrapperEl: null,
      containerEl: null,
      width: undefined,
      height: undefined,
      slides: [],
      isScrolling: undefined,
      length: undefined,
      size: undefined,
      touches: {
        startX: undefined,
        startY: undefined,
        endX: undefined,
        endY: undefined,
        diff: undefined,
        diffX: undefined,
        diddY: undefined,
        currentX: undefined,
        currentY: undefined,
        startTranslate: undefined,
        time: undefined,
        isMoved: undefined
      },
      gridIndex: 0,
      slidesGrid: [],
      translate: 0,
      currentIndex: this.activeIndex,
      transitionDuration: 0,
      rectProp: '',
      maxGridIndex: 0,
      minGridIndex: 0,
      maxTranslate: 0,
      minTranslate: 0,
      interval: null,
      realLength: 0
    };
  },

Methods 定义

// 初始化方法
function setup () {}
// start handler
function onTouchStart (event) {}
// move handler
function onTouchMove (event) {}
// end handler
function onTouchEnd () {}
// 轮播到第几页
function slideTo(newIndex, speed) {}
// 轮播到下一页
function slideNext() {}
// 轮播到上一页
function slidePrev() {}
// 开启自动轮播
function start () {}
// 关闭自动轮播 
function stop () {}
// 设置便宜位置
function setTranslate (newTranslate) {}
// 为 loop 模式创建 dom
function createLoopEl() {}

定义好大概的框架之后,我们就可以一步一步的补充细节了。

过程中的关键点(重要)

loop模式的实现

假设容器宽度为375px, slide length 为 3,loop 模式下 复制节点后的 length 为 5,此时 slideGrid 为 [0, 1, 2, 3, 4]

方法1:当滑动4时,等待动画结束后将位置调整为1,onTouchStart 判断当前的动画是否完成,没有完成的话不允许滑动。这种情况下不能连续滑动,否则容易出现bug,mint-ui 就是类似这样的实现,体验效果不是很好。

方法2:在 onTouchMove 中判断当前位置是否超出限制,如果超出限制,调整位置,这一步比较关键,具体可以看源码。

添加 vetur 代码提示支持

添加完 vetur 后在vscode即可支持 tag 和 attribute 只能提示了。

发布到 NPM

最后一步发布就可以了。

总结

我表达能力太差了,如有错误或想吐槽的地方,尽管侮辱我吧,。接受批评,希望大家点个赞。

你可能感兴趣的:(vue.js,swiper.js)