vue移动端实现(同一路由下)点击滑动转换多个菜单模块

vue移动端实现(同一路由下)点击滑动转换多个菜单模块

收到如题的需求,不用跳转路由进行滑动切换,搜索了半天也没有搜到一个适合我的文章,那就只能自己写了,具体思路借鉴了vue不使用其他插件实现新闻app中左右滑动切换tab菜单和div内容的动画效果(移动端),稍加修改。

首先是效果图

vue移动端实现(同一路由下)点击滑动转换多个菜单模块_第1张图片
(哪个大佬教教我怎么免费把视频做动图QAQ)
可以接受后台数据动态生成菜单列表,利用x轴拖动数据计算判断是否翻页,翻页也是利用x轴位移做的,因为目前只需要两页,所以只写了两个页面的位移,未来如果有更多模块需求再进行优化。

style样式


内容页面

使用vue + element-ui构建

<template>
  <div class="takeNum">
    <el-container>
      <el-main>
        <div
          class="cback"
          @touchstart="touchStart"
          @touchmove="touchMove"
          @touchend="touchEnd"
          ref="back"
        >
          <div class="container cleft"> 
            <ul class="menuUl" :class="addClass()">
              <li v-for="item in itemsLeft" v-bind:key="item.id">
                <div class="right">
                  <p>{
    { item.menuname }}p>
                  <span>
                    等待人数
                    <i>{
    { item.waitnum }}i>
                  span>
                div>
              li>
            ul>
          div>
          <div class="container cright">
            <ul class="menuUl">
              <li v-for="item in itemsRight" v-bind:key="item.id">
                <div class="right">
                  <p>{
    { item.menuname }}p>
                  <span>
                    等待人数
                    <i>{
    { item.waitnum }}i>
                  span>
                div>
              li>
            ul>
          div>
        div>
      el-main>
    el-container>
  div>
template>

接下来是js代码

JS中的data参数设置:

data() {
     
    return {
     
      screenHeight: 0,
      screenWidth: 0,
      items: [
        {
      menuid: "A001", menuname: "综合业务", waitnum: "0" },
        {
      menuid: "A002", menuname: "外汇业务", waitnum: "0" },
        {
      menuid: "A003", menuname: "现金业务", waitnum: "0" },
        {
      menuid: "A006", menuname: "账户业务", waitnum: "0" },
        {
      menuid: "A104", menuname: "转账业务", waitnum: "0" },
        {
      menuid: "AD07", menuname: "对公业务", waitnum: "0" },
        {
      menuid: "A104", menuname: "测试业务", waitnum: "0" },
        {
      menuid: "AD07", menuname: "测试功能", waitnum: "0" },
      ],
      itemsLeft: [],
      itemsRight: [],
      //滑动功能需要的参数
      active: 0,
      currentPlay: "red",
      percent: 0,
      arrs: ["red", "yellow"],
      touch: {
     
        startX: "",
        startY: "",
      },
    };
  },

methods中的函数

1.滑动开始

 //滑动开始
    touchStart(e) {
     
      if (this.itemsRight.length !== 0) {
     
        console.log("滑动开始");
        const touch = e.touches[0];
        this.touch.startX = touch.pageX;
        this.touch.startY = touch.pageY;
      }
    },

2.滑动过程中

//滑动动作
    touchMove(e) {
     
      const touch = e.touches[0];
      //横向和纵向偏离位置
      const deltaX = touch.pageX - this.touch.startX;
      const deltaY = touch.pageY - this.touch.startY;
      if (Math.abs(deltaY) > Math.abs(deltaX)) {
     
        return;
      }
      if (this.currentPlay == "red") {
     
        var left = 0;
        var offsetWidth = Math.min(0, Math.max(-1000, left + deltaX));
      } else {
     
        var left = -1000;
        if (deltaX > 0) {
     
          //判断动作 是左滑还是右滑
          var offsetWidth = Math.min(0, Math.max(-1000, left + deltaX));
        } else {
     
          var offsetWidth = Math.min(-1000, Math.max(-1000 * 2, left + deltaX));
        }
      }
      //记录滑动的距离占屏幕宽度的百分比,如果滑动太少则不切换
      this.percent = deltaX / window.innerWidth;
      //动画中滑块的移动
      this.$refs.back.style["transform"] = `translate3d(${
       offsetWidth}px,0,0)`;
      //设置动画时间
      this.$refs.back.style["transitionDuration"] = 10;
      console.log("");
    },

3.滑动结束

 //滑动结束时
    touchEnd() {
     
      let offsetWidth;
      //   let percent;
      //当前为红色,滑动占比小于-0.1则切换,否则回到原位置
      if (this.currentPlay === "red") {
     
        if (this.percent < -0.1) {
     
          this.currentPlay = "yellow";
          this.active = 1;
          offsetWidth = -1000;
        } else {
     
          offsetWidth = 0;
        }
      } else if (this.currentPlay === "yellow") {
     
        if (this.percent > 0.1) {
     
          this.active = 0;
          this.currentPlay = "red";
          offsetWidth = 0;
        } else {
     
          offsetWidth = -1000;
        }
      }
      //这里的transform是针对最开始的位置而言,而不是移动过程中的位置
      this.$refs.back.style["transform"] = `translate3d(${
       offsetWidth}px,0,0)`;
      this.$refs.back.style["transitionDuration"] = 10;
    },

还有动态附加class

//如果动态创建的功能列表div个数不足4个,就使用css灵活居中布局,
//如果超过4个才使用三个div一行的布局模式,第四个会在第一个div下方摆放而不是在第二排居中位置。
addClass() {
     
      if (this.itemsLeft.length < 4) {
     
        return "menuUl_1";
      } else {
     
        return "menuUl_2";
      }
    },

剩下就是在mouted钩子函数阶段,将数组处理成两个数组,后面会分别放入两个页面。

mounted() {
     
    this.itemsLeft = this.items.slice(0, 6);
    this.itemsRight = this.items.slice(6, 12);

  },

关于滑动

实现原理:
判断第二屏是否存在(items长度是否大于6),存在则touchStart监听滑动的坐标,标记初始屏为red,touchMove先根据计算判断滑动的动作是左还是右,其中处于第一屏向左滑无效果,处于第二屏向右侧滑动时效果为可滑动但位移不变还是复原在第二屏视图,当监听到用户正常从第一屏滑动距离满足一定长度时,touchEnd切换成第二屏,标记为yellow,

主要完成位移的代码是:

this.$refs.back.style["transform"] = `translate3d(${
       offsetWidth}px,0,0)`;

另外,本文我设置了一屏的长度是1000px。

我是程序小桃,深知本文功能还有很多可改进的地方,各位如果觉得有用或者感兴趣,请多多交流、点赞和评论呀~

你可能感兴趣的:(vue项目踩坑,javascript,vue)