Vue -- 点击左右按钮可滑动一屏

883 阅读1分钟

效果图:

第一页: image.png 第二页: image.png

实现思路: 1、列表横向排列可以使用flex布局解决,主要逻辑在点击左右按钮时操作

-----看懂这个很关键---- image.png

如上图,蓝色为外层div,红色为内层div; 内层div装有列表的各项item,所以它的宽度可能会大于外层div的宽度。外层div采用定宽,同时设置overflow: hidden,使内层div突出的部分隐藏起来。通过设置内层div的transform:translateX来左右移动。

image.png

上代码:

<div class="top">//class="top"为可视宽度
   //左箭头
  <div class="left" @click="navPrev">
    <img src="@/assets/images/equipment/default.png" alt="">
  </div>
  //内容
  <div class="center" ref="devInsall">
    <div :class="item.isChoose==true?'active_item':'item'"
      :style="{transform:'translateX(-'+state.move+'px)'}"
      v-for="(item,index) in state.installList" :key="index"
      @click="handlerDeviceInstall(item)">
      <img :src="item.productUrl" alt="">
      <p style="color: #FFFFFF;">{{item.productName}}</p>
      <p style="color: #CFD5DF;">{{item.installDeviceTotal}}</p>
    </div>
  </div>
  
  //右箭头
  <div class="right" @click="navNext" v-if="state.installList.length>15">
    <img src="@/assets/images/equipment/right.png" alt="">
  </div>
</div>

js部分:

//vue3.0 写法
<script setup>
import { reactive, ref, onMounted, nextTick } from "vue";
  const state = reactive({
      //定义三个参数
      move: 0,//移动位置
      realWidth: 0,//实际宽度
      viewWidth: 0,//可视宽度
      installList:[]//列表
  })
  //获取宽度
  const rollTemp = () => {
  nextTick(() => {
    //获取整个菜单实际宽度、state.installList是后端返回的,118是代表每一个的宽度
    state.realWidth = state.installList.length * 118
    console.log('内容总宽度-----', state.realWidth)
    // 获取菜单在当前页面可视宽度
    state.viewWidth = devInsall.value.clientWidth
    console.log('可视宽度', state.viewWidth)
    // 窗口大小变化时触发。实时更新可视宽度
    window.onresize = () => {
      return (() => {
        state.viewWidth = devInsall.value.clientWidth
        if (state.move > state.realWidth - state.viewWidth - 118) {
          state.move = state.realWidth - state.viewWidth;
          console.log('窗口变化时move', state.move)
        }
      })()
    }
  })
}

const navPrev = () => {//点击左箭头
  if (state.move > 118) {
    state.move = state.move - state.viewWidth
    console.log('向左边移动===>', state.move)
  } else {//停止
    state.move = 0
  }
}

const navNext = () => {//点击右箭头
  if (state.realWidth < state.viewWidth) {//内容少于可视宽度时,不需要移动
    return false
  } else {
    //如果偏移量+可视宽度+118大于内容总长度;表示已经到底了
    if ((state.move + state.viewWidth + 118) > state.realWidth) {
      console.log('到底啦')
      state.move = state.move
    } else {
      //移动一屏
      state.move = state.move + state.viewWidth
      console.log('我还要move', state.move)
    }
  }
}

</script>

css代码:

.top {
    display: flex;
    justify-content: space-between;
    width: 100%;
    height: 100px;
    background-color: #0f315f;
    .left {
      position: relative;
      width: 44px;
      height: 100%;
      background-color: #1d528f;
      img {
        position: absolute;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
        width: 26px;
        height: 32px;
      }
    }
    .right {
      position: relative;
      width: 44px;
      height: 100%;
      background-color: #1d528f;
      cursor: pointer;
      img {
        position: absolute;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
        width: 16px;
        height: 32px;
      }
    }
    .center {
      display: flex;
      justify-content: flex-start;
      width: calc(100% - 98px);
      overflow: hidden;
      white-space: nowrap;
      .item {
        display: flex;
        flex-direction: column;
        justify-content: space-around;
        align-items: center;
        min-width: 88px;
        height: 98px;
        transition: transform 0.2s;
        margin-left: 30px;
        cursor: pointer;
        img {
          width: 40px;
          height: 40px;
        }
        p {
          font-size: 12px;
        }
      }
      .active_item {
        display: flex;
        flex-direction: column;
        justify-content: space-around;
        align-items: center;
        background: linear-gradient(180deg, #0f315f 0%, #409eff 100%);
        min-width: 88px;
        height: 98px;
        margin-left: 30px;
        cursor: pointer;
        img {
          width: 40px;
          height: 40px;
        }
        p {
          font-size: 12px;
        }
      }
    }
  }