vue better-scroll 实现饿了么菜单联动滚动

better-scroll 地址: https://better-scroll.github.io/docs/zh-CN/guide/

效果展示
在这里插入图片描述

1.首先安装better-scroll

https://better-scroll.github.io/docs/zh-CN/guide/how-to-install.html#npm

2.左侧菜单代码,首先渲染左侧菜单

  1. 左侧菜单**
解释:
 ref="menuScroll"  左侧菜单ref
 currentIndex :计算属性,动态添加样式
注意:

  <div class="menu-left" ref="menuScroll">
        <ul>
          <li :class="{'li-active':currentIndex === index}" v-for="(item,index) in shopInfo.menu" :key="index" @click="handleLi(index)">
            <img style="width:.45rem;margin-right:.2rem" v-if="item.icon_url" :src="item.icon_url" alt="" srcset=""> {{item.name}}
          </li>
        </ul>
      </div>
  1. 右侧菜单代码
解释:
 ref="foodScroll"  右侧菜单ref
 shopInfo  后台返回的所有数据

<!-- 右侧菜单 -->
      <div class="menu-right" ref="foodScroll">
        <ul>
          <li v-for="(item,index) in shopInfo.menu" :key="index" class="food-list-hook">
            <!-- 内容上 -->
            <div class="category-title">
              <strong>{{item.name}}</strong>
              <span>{{item.description}}</span>
            </div>
            <div v-for="(food,idx) in item.foods" :key="idx" class="menu-right-content">
              <div><img :src="food.image_path" alt="" srcset=""></div>
              <div class="detail-good">
                <div style="font-weight:bold;font-size:.35rem;">{{food.name}}</div>
                <div class="description">{{food.description | fontNumber}}</div>
                <div class="month"><span>月售{{food.month_sales}}</span><span>好评{{food.satisfy_rate}}</span></div>
                <div class="price-count">
                  <div style="margin-right:auto;color:#ec6206;"> ¥{{food.activity.fixed_price}}</div>
                  <CartControll :food="food" @decreaseCount="decrease" />
                </div>
              </div>
            </div>
          </li>
        </ul>
      </div>

右侧数据结构
在这里插入图片描述
3.js代码

<script>
import BScroll from "better-scroll";  //导入better-scroll
export default {
  name: 'goods',
  data () {
    return {
      shopInfo: {}, //所有要用到的数据
      menuScroll: {},//左侧商品滚动对象
      foodScroll: {},//右侧商品滚动对象
      scrollY: 0,//右侧当前滚动的值
      listHeight: []//所有 ul>li 每个li的高度
    }
  },
  created () {
    this.getData()
  },
  computed: {
    //根据右侧滚动的位置,确定左侧菜单的下标
    currentIndex () {
      for (let i = 0; i < this.listHeight.length; i++) {
        let hight1 = this.listHeight[i]
        let hight2 = this.listHeight[i + 1]
        //判断是否在两个高度之间 如果是 返回 当前索引
        if (this.scrollY >= hight1 && this.scrollY < hight2) {
          return i
        }
      }
      return 0 
    }
  },
  methods: {
   //获取所有数据
    getData () {
      this.$axios('/api/profile/batch_shop').then((res) => {
        res.data.recommend.forEach(recommend => {
          recommend.items.forEach(item => {
            item.count = 0; // 为每项添加数量
          });
        });
        res.data.menu.forEach(menu => {
          menu.foods.forEach(food => {
            food.count = 0; // 为每项添加数量
          });

        });
        this.shopInfo = res.data  
        //当所有DOM更新完在执行下面的方法
        this.$nextTick(() => {
          // DOM已经更新
          this.initScroll();
          // 计算12个区的高度
          this.calculateHeight();
        });

      })
    },
    // 初始化 better-scroll
    initScroll () {
    //拿到左侧菜单的滚动对象
      this.menuScroll = new BScroll(this.$refs.menuScroll, {
        click: true
      });
      
	 //拿到右侧菜单的滚动对象
      this.foodScroll = new BScroll(this.$refs.foodScroll, {
        probeType: 3, //实时滚动
        click: true
      });
      //监听 scroll 事件
      this.foodScroll.on("scroll", pos => {
        this.scrollY = Math.abs(Math.round(pos.y)); //取绝对值
        console.log(this.scrollY);
      });
      this.updated()
    },
    
      //解决better-scroll因为图片没有下载完导致的滚动条高度不够,无法浏览全部内容的问题。
      //原因是better-scroll初始化是在dom加载后执行,此时图片没有下载完成,导致滚动条高度计算不准确。
      //利用图片的complete属性进行判断,当所有图片下载完成后再对scroll重新计算。
    updated () {
      let img = document.getElementsByClassName('menu-right')[0].getElementsByTagName('img')
      // console.log(img);
      let count = 0
      let length = img.length
      if (length) {
        let timer = setInterval(() => {
          if (count == length) {
            //如果图片都加载完了,重新刷新一下 scroll的滚动高度
            this.foodScroll.refresh()  
            clearInterval(timer)
          } else if (img[count].complete) {
            count++
          }
        }, 0)
      }

    },
    //计算每个li的高度
    calculateHeight () {
      let foodlist = this.$refs.foodScroll.getElementsByClassName(
        "food-list-hook"
      );
      // 每个区的高度添加到数组中
      let height = 0;
      this.listHeight.push(height);  //从0开始 先push 0到listHeight数组中

	//遍历循环 foodlist 将每个 li 的高度添加到数组中
      for (let i = 0; i < foodlist.length - 1; i++) {
        let item = foodlist[i];
        // 累加
        height += item.clientHeight;
        this.listHeight.push(height);
      }
      console.log(this.listHeight); //得到的所有每个li 高度的数组
    },
    
    //点击左侧列表跳转到右侧相应位置
    handleLi (index) {
    //获取右侧所有类为food-list-hook节点
      let foodList = this.$refs.foodScroll.getElementsByClassName('food-list-hook')
      //点击谁就拿到谁
      let el = foodList[index]
      // 跳转到点击的 food-list-hook 节点  花费时间为 250 毫秒
      this.foodScroll.scrollToElement(el, 250)
    }
  },

  components: {
    BScroll
  }
}
</script>
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Vue是一种用于构建用户界面的渐进式JavaScript框架,它可以帮助开发者更高效地构建单页面应用程序。而vue-better-scroll是基于Vue的一款优秀的滚动插件,它能够实现更流畅的滚动效果,并且支持上下左右的滚动联动效果。 如果需要实现左右侧菜单联动效果,我们可以通过使用vue-better-scrollscrollToElement方法来实现。首先,我们需要在Vue中引入vue-better-scroll插件并进行配置。 在Vue实例的data中,我们可以定义左右两个菜单的数据,例如leftMenu和rightMenu,并在created生命周期中初始化数据。然后,在mounted生命周期中,我们可以通过refs属性获取到两个菜单容器的DOM元素。 接下来,我们需要监听左边菜单的点击事件,当点击左边菜单的某个选项时,我们可以通过调用vue-better-scrollscrollToElement方法,将右边菜单滚动到对应的位置。通过传递目标元素的选择器或具体的DOM元素,我们可以实现左右菜单联动效果。 具体实现时,我们可以在左边菜单的点击事件中,使用this.$refs来访问右边菜单容器,并调用scrollToElement方法,将目标元素滚动到可视区域。通过传递选择器或具体DOM元素作为参数,我们可以精确控制滚动的位置。 同时,为了视觉上更好的效果,我们还可以给目标元素添加样式,如高亮当前选中项,以提升用户体验。 最后,通过一系列的事件处理和样式设置,我们就可以实现左右侧菜单联动demo了。 以上就是使用Vuevue-better-scroll实现左右侧菜单联动demo的大致思路和步骤。通过合理运用这两个工具,我们可以轻松地实现出一个流畅、友好的用户界面效果

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

一头小绵羊

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

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

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

打赏作者

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

抵扣说明:

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

余额充值