vue上下滑动翻页组件

demo地址 http://106.13.201.82/demo/page_change.html

page_change.vue

<template>
  <div class="flex" :class="direction" :style="{width,height:height}" ref="hei">
    <slot></slot>
  </div>
</template>
<script>
  var windowHeight = document.documentElement.clientHeight||window.innerHeight;
  var windowWidth =document.documentElement.clientWidth||window.innerWidth;
  export default {
    data:function () {
      return {
        preIndex:0,
        curIndex:0,
        startX:0,
        startY:0,
        endX:0,
        endY:0,
        len:0,
        '',
        height:'',
        isDown:false,
        num:this.direction.indexOf('reverse')>-1?-1:1,
        distance:50,
      }
    },
    props:{
      //距离
      distance:{
        type: Number,
        default:50
      },
      //方向
      direction:{
        type: String,
        default:'column'//row|row-reverse|column|column-reverse
      },
    },
    mounted: function () {
      this.scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
      this.scrollLeft = document.documentElement.scrollLeft|| document.body.scrollLeft;

      this.len=this.$refs.hei.children.length;
      if(this.direction==='row'||this.direction==='row-reverse'){
        this.width=this.len*windowWidth+'px';
        this.height=windowHeight+'px';
      }else{
        this.width=windowWidth+'px';
        this.height=this.len*windowHeight+'px';
      }

      window.addEventListener('touchstart', this.touchstart);
      window.addEventListener('touchmove', this.touchmove);
      window.addEventListener('touchend', this.touchend);
      this.$nextTick(()=>{
        if(this.direction==='row'||this.direction==='row-reverse') {
          this.curIndex=Math.round(this.scrollLeft/windowWidth)
        }else{
          this.curIndex=Math.round(this.scrollTop/windowHeight)
        }
      })
    },
    methods:{
      touchstart (e) {
        this.isDown=true;
        this.startX = e.touches[0].clientX;
        this.startY = e.touches[0].clientY;
      },
      touchmove(e){
        if(!this.isDown){
          this.isDown=true;
          this.startX = e.touches[0].clientX;
          this.startY = e.touches[0].clientY;
          return;
        }else{
          this.endX = e.touches[0].clientX;
          this.endY = e.touches[0].clientY;
        }
      },
      touchend() {
        if(!this.isDown){
          return;
        }
        this.isDown=false;
        this.preIndex=this.curIndex;
        if(this.direction==='row'||this.direction==='row-reverse'){
          if(this.startX-this.endX>this.distance){
            this.curIndex=this.curIndex+this.num;
          }else if(this.startX-this.endX<-this.distance){
            this.curIndex=this.curIndex-this.num;
          }
          window.scrollTo({
            left:this.curIndex*windowWidth,
            behavior:'smooth'
          })
        }else{
          if(this.startY-this.endY>this.distance){
            this.curIndex=this.curIndex+this.num;
          }else if(this.startY-this.endY<-this.distance){
            this.curIndex=this.curIndex-this.num;
          }
          window.scrollTo({
            top:this.curIndex*windowHeight,
            behavior:'smooth'
          })
        }
        if(this.curIndex>this.len-1){
          this.curIndex=this.len-1;
        }else if(this.curIndex<0){
          this.curIndex=0;
        }
        this.$emit('pageChange',{
          direction:this.direction,
          curIndex:this.curIndex,
          preIndex:this.preIndex,
        })
      }
    }
  };
</script>
<style  type="text/css" lang="less" scoped>
  .flex{
    display:flex;
  }
  .column{
    flex-direction: column;
  }
  .column-reverse{
    flex-direction: column-reverse;
  }
  .row{
    flex-direction: row;
  }
  .row-reverse{
    flex-direction: row-reverse;
  }
</style>
原文地址:https://www.cnblogs.com/caoke/p/12491992.html