Vue3 + Ts 封装点击切换,左右滚动的商品展示组件

效果图

点击左右按钮 图片均可实现左右滚动切换效果
在这里插入图片描述

直接上代码

<template>
  <div class="details">
    <div class="swiperBox">
      <el-carousel :autoplay="false" ref="swiperRef">
        <el-carousel-item
          v-for="(item, index) in imgList"
          :key="index"
          :name="`${index}`"
        >
          <img style="width: 100%; height: 100%" :src="item" />
        </el-carousel-item>
      </el-carousel>
    </div>
    <div class="arrowBox">
      <div
        class="iconBox"
        :style="swiperAct == 0 ? 'pointer-events: none' : ''"
        @click="arrowBold('left')"
      >
        <el-icon><ArrowLeftBold /></el-icon>
      </div>
      <div class="imgWrap">
        <div class="imgBox" id="imgBox" ref="imgBoxRef">
          <div
            class="img"
            :id="`img${index}`"
            :style="
              swiperAct == index
                ? 'border: 2px solid #eb0045;'
                : 'border: 2px solid #f8f8f8;'
            "
            v-for="(item, index) in imgList"
            :key="index"
            @click="arrowClick(index)"
          >
            <img style="width: 100%; height: 100%" :src="item" />
          </div>
        </div>
      </div>
      <div
        class="iconBox"
        :style="swiperAct == imgList.length - 1 ? 'pointer-events: none' : ''"
        @click="arrowBold('right')"
      >
        <el-icon><ArrowRightBold /></el-icon>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { reactive, toRefs, ref, onMounted, onUnmounted } from "vue";

const swiperRef = ref();
const imgBoxRef = ref();

let data = reactive({
  imgList: [
    "https://5b0988e595225.cdn.sohucs.com/images/20200430/fe07a3826cb548ad9d9dd1ac1b59b26e.jpeg",
    "https://p4.itc.cn/images01/20210414/348f8b1417d3490891ae8cefda30466f.jpeg",
    "https://image.uc.cn/s/wemedia/s/upload/2021/496ac52bdaab446a7993e6507ecef696.jpg",
    "https://gss0.baidu.com/-Po3dSag_xI4khGko9WTAnF6hhy/zhidao/pic/item/ae51f3deb48f8c546fe467cd3b292df5e0fe7f19.jpg",
    "https://p3.toutiaoimg.com/origin/pgc-image/8bb2a8d88e474410b2fd9bc0106c7425?from=pc",
    "https://p7.itc.cn/images01/20201001/501434b4b09a4500bad79cb401572fc5.jpeg",
    "https://img0.baidu.com/it/u=1275095085,1961143463&fm=253&fmt=auto&app=120&f=JPEG?w=1280&h=800",
    "https://img2.baidu.com/it/u=1966616150,2146512490&fm=253&fmt=auto&app=120&f=JPEG?w=751&h=500",
    "https://img0.baidu.com/it/u=1049144354,3589714554&fm=253&fmt=auto&app=120&f=JPEG?w=1280&h=800",
  ],
  swiperAct: 0,
  isScoll:true
});

let { imgList, swiperAct,isScoll } = toRefs(data);
// 鼠标点击事件
let clickHandle = (e: any) => {
  if (e.x <= 518) {
    // 调用方法向左滑动
    scrollRight("left");
  }
  if (e.x >= 660) {
    // 调用方法向右滑动
    scrollRight("right");
  }
};
// 选中的图片索引
let arrowClick = (index: any) => {
  swiperRef.value.setActiveItem(index);
  swiperAct.value = index;
};
// 上下切换图片
let arrowBold = (type: any) => {
  let value: any;
  if (type == "left") {
    value = swiperAct.value - 1;
    scrollRight("left");
  }
  if (type == "right") {
    value = swiperAct.value + 1;
    scrollRight("right");
  }
  // 现实具体图片
  swiperRef.value.setActiveItem(value);
  // 当前现实的图片
  swiperAct.value = value;
};
/**
 * 左右移动事件
 * @param type 向左/右移动
 */
let scrollRight = (type?: any) => {
  if(!isScoll.value)return
  // 节流
  isScoll.value= false
  /**
   * @param 618 可视化宽度 最大的盒子
   * @param 5 可视化中现实数量
   * @param imgList 数组长度
   */
  const allLength = Math.floor((618 / 5) * imgList.value.length);
  // 获取包裹商品卡片的div盒子的宽度
  const boxLength = imgBoxRef.value.clientWidth;
  // 数组总长度比大盒子的宽度还要小
  if (allLength < boxLength) return;
  // 获取包裹商品卡片的div盒子
  const listEl = imgBoxRef.value;
  // 获取定位的 left 值
  const rightMove = Math.abs(parseInt(window.getComputedStyle(listEl)?.left));
  /**
   * @param rightMove 定位的 left 值
   * @param boxLength 包裹商品卡片的div盒子的宽度
   * @param 124 是单个商品卡片的宽度
   * @param allLength 可视化宽度 最大的盒子
   */
  if (rightMove + boxLength + 124 > allLength) {
    if (type == "left") {
      listEl.style.left = "-" + (rightMove - 124) + "px";
    } else {
      listEl.style.left = "-" + (allLength - boxLength) + "px";
    }
  } else {
    if (type == "left") {
      if (rightMove - 124 < 124) {
        listEl.style.left = "0px";
      } else {
        listEl.style.left = "-" + (rightMove - 124) + "px";
      }
    } else {
      listEl.style.left = "-" + (rightMove + 124) + "px";
    }
  }
  setTimeout(()=>{
  	isScoll.value= true
  },500)
};

onMounted(() => {
  // 可视化宽度 最大的盒子 添加点击事件
  imgBoxRef.value.addEventListener("click", clickHandle);
});
onUnmounted(() => {
  // 可视化宽度 最大的盒子 移除点击事件
  if (imgBoxRef.value) {
    imgBoxRef.value.removeEventListener("click", clickHandle);
  }
});
</script>

<style scoped lang="scss">
.details {
  margin-top: 50px;
  .arrowBox {
    display: flex;
    margin-top: 32px;
    height: 90px;
    align-items: center;
    width: 698px;
    .imgWrap {
      flex: 1;
      height: 90px;
      position: relative;
      margin: 0 10px;
      overflow: hidden;
      .imgBox {
        width: 100%;
        height: 90px;
        white-space: nowrap;
        position: absolute;
        left: 0px;
        transition: all 0.3s;
        .img {
          cursor: pointer;
          display: inline-block;
          width: 114px;
          height: 90px;
          margin-right: 12px;
          box-sizing: border-box;
        }
        .img:last-child {
          margin-right: 0;
        }
      }
    }
    .iconBox {
      line-height: 90px;
      width: 30px;
      height: 100%;
      background: #9f9f9f;
      color: #fff;
      text-align: center;
      cursor: pointer;
    }
    .iconBox:hover {
      background: #232836;
    }
  }
  .swiperBox {
    width: 698px;
    height: 400px;
    border-radius: 6px;
    overflow: hidden;
    :deep(.el-carousel) {
      height: 100%;
    }
    :deep(.el-carousel__container) {
      height: 100%;
    }
    :deep(.el-carousel__indicators) {
      display: none;
    }
    :deep(.el-carousel__arrow) {
      display: none;
    }
    .el-carousel__item h3 {
      color: #475669;
      opacity: 0.75;
      height: 100%;
      line-height: 400px;
      margin: 0;
      text-align: center;
    }
    .el-carousel__item:nth-child(2n) {
      background-color: #99a9bf;
    }

    .el-carousel__item:nth-child(2n + 1) {
      background-color: #d3dce6;
    }
  }
}
</style>
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

卷不动了阿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值