«

实现手机端左右联动better-scroll(vue3)

yang 发布于 阅读:316 vue3阶段


使用步棸

1.安装滚动插件

yarn add better-scroll@1.11.1 -D

2.引入插件实例化

import BScroll from "better-scroll"; //引入插件

3.定义左右两边实例

const bs1 = ref(); //左边商品分类滚动实例
const bs2 = ref(); //右边商品列表滚动实例

4.初始化better - scroll

onMounted(() => {
  nextTick(() => {
    //左边商品列表滚动实例
    bs1.value = new BScroll(".aside", {
      probeType: 3,
      click: true, //让滚动的元素可以被点击
    });

    //右边商品列表滚动实例
    bs2.value = new BScroll(".list", {
      probeType: 3,
      click: true, //让滚动的元素可以被点击
    });

    //计算所有商品标题的位置
    const arr = computed(() => {
      let data: number[] = [];
      list.value.map((v: unknown, i: any) => {
        const title = document.querySelector("#title" + i) as any;
        const title0 = document.querySelector("#title" + 0) as any;
        data.push(title.offsetTop - title0.offsetTop);
      });
      return data;
    });

    //滚动右边商品列表时
    bs2.value.on("scroll", (pos: any) => {
      let y = Math.abs(pos.y);
      // console.log(y);

      // 根据每个标题高度循环遍历来实现标题与左边的联动
      for (let i = 0; i < arr.value.length - 1; i++) {
        if (y >= arr.value[i] && y < arr.value[i + 1]) {
          active.value = i;

          // 5.实现跟左边标题的滑动效果
          bs1.value.scrollToElement("#cate" + i, 400);
        }
      }
      // console.log(document.querySelector("#title0"));
    });
  });
});

6.左联右实现

const show = (i: any) => {
  bs2.value.scrollToElement("#title" + i, 400);
};

具体项目体现,可以根据具体需求来改编

<template>
  <div class="goods">
    <!-- 左边商品分类 -->
    <aside class="aside">
      <van-sidebar v-model="active">
        <van-sidebar-item
          v-for="(v, i) in cate"
          :title="v"
          :key="i"
          @click="show(i)"
          :id="'cate' + i"
        />

        <!-- 占位符 -->
        <div class="aside_place"></div>
      </van-sidebar>
    </aside>

    <!-- 右边商品列表 -->
    <div class="list">
      <ul>
        <li v-for="(v, i) in list" :key="i" :id="v.name">
          <h3 class="list-title" :id="'title' + i">
            {{ v.name }}
          </h3>
          <van-card
            v-for="(v2, i2) in v.foods"
            :key="i2"
            :price="v2.price.toFixed(2)"
            :desc="v2.goodsDesc"
            :title="v2.name"
            :origin-price="v2.id"
            :thumb="v2.imgUrl"
            :tag="v2.category"
            @click="detail(v2)"
          >
            <template #tags>
              <van-tag round type="primary">特价</van-tag>&emsp;
              <van-tag round type="danger">八折</van-tag>
            </template>
            <template #footer>
              <van-stepper
                v-model="v2.num"
                theme="round"
                button-size="22"
                disable-input
                :min="0"
                :max="100"
                v-on:click.native.stop
              />
            </template>
          </van-card>
        </li>
        <!-- 占位符 -->
        <div class="place"></div>
      </ul>
    </div>

    <!-- 购物车 -->
    <shop-cart></shop-cart>
  </div>
</template>

<script lang="ts" setup>
import ShopCart from "@/components/ShopCart.vue";
import { ref, onMounted, nextTick, computed } from "vue";
import { useRouter } from "vue-router";
import { $_goodslist } from "@/apis/goods";
import { Info } from "@/stores/counter";
const store = Info();
let goodsList = ref<Array<any>>([]);
const active = ref(0);
const bs1 = ref(); //左边商品分类滚动实例
const bs2 = ref(); //右边商品列表滚动实例
const cate = ref<Array<any>>([]); //左边分类名字
const list = ref<Array<any>>([]); //右边数据
let router = useRouter(); //获取全局最大的实例路由对象
//引入插件
import BScroll from "better-scroll"; //引入插件

$_goodslist().then((res) => {
  if (store.goods.length > 0) return;
  for (let obj of res.data.data)
    for (let item of obj.foods) {
      item.num = 0;
    }
  goodsList.value = res.data.data;
  store.GoodsChange(goodsList.value);
  // 商品分类(pinai数据)
  cate.value = store.goods.map((v: any) => v.name);
  list.value = res.data.data;
  console.log(res);
});

// 初始化better - scroll;
onMounted(() => {
  nextTick(() => {
    //左边商品列表滚动实例
    bs1.value = new BScroll(".aside", {
      probeType: 3,
      click: true, //让滚动的元素可以被点击
    });

    //右边商品列表滚动实例
    bs2.value = new BScroll(".list", {
      probeType: 3,
      click: true, //让滚动的元素可以被点击
    });

    //计算所有商品标题的位置
    const arr = computed(() => {
      let data: number[] = [];
      list.value.map((v: unknown, i: any) => {
        const title = document.querySelector("#title" + i) as any;
        const title0 = document.querySelector("#title" + 0) as any;
        data.push(title.offsetTop - title0.offsetTop);
      });
      return data;
    });

    //滚动右边商品列表时
    bs2.value.on("scroll", (pos: any) => {
      let y = Math.abs(pos.y);
      // console.log(y);

      // 根据每个标题高度循环遍历来实现标题与左边的联动
      for (let i = 0; i < arr.value.length - 1; i++) {
        if (y >= arr.value[i] && y < arr.value[i + 1]) {
          active.value = i;

          // 实现跟左边标题的滑动效果
          bs1.value.scrollToElement("#cate" + i, 400);
        }
      }
      // console.log(document.querySelector("#title0"));
    });
  });
});

// 左联右
const show = (i: any) => {
  bs2.value.scrollToElement("#title" + i, 400);
};

// 跳转到详情页面request
const detail = (v2: any) => {
  router.push({ path: "/detail", query: { v2: JSON.stringify(v2) } }); //跳转路由
};
</script>

<style lang="scss" scoped>
// 隐藏所有的滚动条
::-webkit-scrollbar {
  display: none;
  // Chrome Safari
}
.goods {
  display: flex;
  height: 100%;
  overflow-y: scroll;

  // 左边商品分类
  .aside {
    width: 30%;
    background: #f7f8fa;
    // overflow-y: scroll;
    overflow: hidden;

    .van-sidebar {
      width: 100%;
    }

    .van-sidebar-item--select::before {
      background-color: #f60;
    }

    // 占位符
    .aside_place {
      height: 85px;
    }
  }
  // 右边
  .list {
    width: 1px;
    flex-grow: 1;
    // overflow-y: auto;
    overflow: hidden;

    .list-title {
      line-height: 32px;
      background: #f4f4f4;
      border-left: 2px solid #ccc;
      font-size: 16px;
      color: #666;
      text-indent: 10px;
    }

    .van-card {
      width: 100%;
      padding: 6px;
      background: #fff;
    }
    .van-card__price {
      color: #f00;
    }

    // 占位符
    .place {
      height: 85px;
    }
  }
}
</style>

pinai数据

export const Info = defineStore("Info", () => {
     // 商品
  let goods = ref<any>([]);
  let GoodsChange = (val: any) => {
    goods.value = val;
  };
  // 商品数量增加减少(后台数据没有,循环给每个商品添加一个属性判断)
  let addNum = (val: any, num: any) => {
    for (let obj of goods.value) {
      for (let arr of obj.foods) {
        if (arr.id === val.id) {
          arr.num += num;
        }
      }
    }
  };

     return {
    goods,
    GoodsChange,
    addNum,
  };
});

版权所有:微4e
文章标题:实现手机端左右联动better-scroll(vue3)
除非注明,文章均为 微4e 原创,请勿用于任何商业用途,禁止转载

推荐阅读:


扫描二维码,在手机上阅读
请先 登录 再评论