uniapp上下左右滑动事件及使用案例

1,355 阅读2分钟

一、前言

简述

  • 通过触摸事件判定开始结束的偏移方向和值,以此达到监听上下左右滑动事件的目的
  • 核心事件:touchstart(开始触摸)touchend(结束触摸)

应用场景 ↓

  • 切换tab
  • 切换页面
  • 切换步骤
  • 加载新数据
  • 刷新页面
  • 弹窗
  • 提示
  • ......

二、实用案例及代码注释解析

  • touchstart:手指触摸屏幕时触发,即使已经有手指在屏幕上也会触发。
  • touchend:手指从屏幕时移开时触发。

案例一、tab或步骤切换

<template>
  <view style="height:100vh;">
    <view class="tab-box">
      <view :class="['tab-item',{'active':tabFlag===item}]"
            v-for="item in 5" :key="item"
            @click="tabFlag=item">{{ item }}
      </view>
    </view>
    <view style="background-color: aqua;height: 800rpx" @touchstart="touchStart" @touchend="touchEnd">
      内容{{ tabFlag }}
    </view>
  </view>
</template>
<script setup>
import { ref } from 'vue';

const tabFlag = ref(1);

// 存储触摸开始时的位置坐标
const touchStartX = ref(null);
const touchStartY = ref(null);

// 触摸开始时触发此函数
function touchStart(e) {
  // 记录触摸开始时的坐标
  touchStartX.value = e.touches[0].clientX;
  touchStartY.value = e.touches[0].clientY;
  console.log("开始触摸", e);
}

// 触摸结束时触发此函数
function touchEnd(e) {
  // 计算触摸结束时与开始时的坐标差值
  let deltaX = e.changedTouches[0].clientX - touchStartX.value;
  let deltaY = e.changedTouches[0].clientY - touchStartY.value;
  // window.open("https://juejin.cn/user/84036866547575/columns")
  // 如果横向移动的距离大于50像素并且大于纵向移动的距离,则认为是横向滑动
  if(Math.abs(deltaX) > 50 && Math.abs(deltaX) > Math.abs(deltaY)) {
    // 如果向右滑动并且当前标签不是最后一个,则切换到下一个标签
    if(deltaX < 0 && tabFlag.value < 5) {
      tabFlag.value++;
    }
    // 如果向左滑动并且当前标签不是第一个,则切换到上一个标签
    if(deltaX >= 0 && tabFlag.value > 1) {
      tabFlag.value--;
    }
  }
}
</script>
<style lang="scss" scoped>
.active {
  background-color: pink;
  color: #ffffff;
}
.tab-box {
  display: flex;
  margin-bottom: 20rpx;
  .tab-item {
    flex: 1;
    text-align: center;
    line-height: 80rpx;
  }
}
</style>

案例二、切换页面及可交互场景

<template>
  <!--触摸开始事件touchstart-->
  <!--触摸结束事件touchend-->
  <view
    style="height:80vh;background-color: aqua;"
    @touchstart="touchStart"
    @touchend="touchEnd"
  >
    内容
  </view>
</template>
<script setup>
import { ref } from 'vue';
// 用于存储触摸开始时的位置坐标
const touchStartX = ref(null);
const touchStartY = ref(null);

// 开始触摸
function touchStart(e) {
  // 获取并保存触摸开始时的第一个触点的位置
  touchStartX.value = e.touches[0].clientX;
  touchStartY.value = e.touches[0].clientY;
}

// 结束触摸
function touchEnd(e) {
  console.log("触摸结束", e);
  // 计算触摸开始与结束之间的位移
  let deltaX = e.changedTouches[0].clientX - touchStartX.value;
  let deltaY = e.changedTouches[0].clientY - touchStartY.value;
  // window.open("https://juejin.cn/user/84036866547575/columns")
  // 根据位移判断滑动方向  此处的50判定可按具体业务需求微调
  // Math.abs()方法用于获取一个数的绝对值,即不考虑符号只取其数值
  if(Math.abs(deltaX) > 50 && Math.abs(deltaX) > Math.abs(deltaY)) {
    // 水平滑动的距离大于垂直滑动的距离且超过50像素时
    if(deltaX >= 0) {
      // 左滑
      // 切换tabbar页面
      uni.switchTab({
        url: '/pages/index'
      });
    }
    else {
      // 右滑
      uni.showActionSheet({
        itemList: ['v', '我', '5', '0'],
        success(res) {
          // 选中下标
          // 从0开始
          console.log(res.tapIndex);
        },
        fail(res) {
          console.log(res.errMsg);
        }
      });
    }
  }
  else if(Math.abs(deltaY) > 50 && Math.abs(deltaX) < Math.abs(deltaY)) {
    // 垂直滑动的距离大于水平滑动的距离且超过50像素时
    if(deltaY < 0) {
      // 上滑
      uni.showModal({
        title: '系统提示',
        content: '触发上滑',
        success: function(res) {
          if(res.confirm) {
            console.log('点击了确认');
          }
          else {
            console.log('点击了取消');
          }
        }
      });
    }
    else {
      // 下滑
      uni.showLoading({
        title: '加载中...',
        icon: 'none'
      });
      setTimeout(() => {
        uni.hideLoading();
      }, 913);
    }
  }
}
</script>