vue |通过BetterScroll创建动态菜单

时间:2021-01-27 13:55:07   收藏:0   阅读:0

参考:https://juejin.cn/post/6844903655108280328

效果

技术图片

BetterScroll

//安装
npm install better-scroll --save
//导入
import Bscroll from "better-scroll";

滚动原理:需要一个固定高度的父容器,然后在其基础上进行滚动。

//设scrollH为父容器高度,例:
this.scrollH= window.innerHeight - 150
技术图片

整体结构

相关数据

data() {
  return {
      foodList:[],//菜品信息
      scrollH:‘‘,//滚轮窗口的高度
      heightList:[],//储存位置
      scrollY:‘‘,//滚动距离
  };
},

例-foodList数据结构:

foodList:[
    {name:‘菜类‘,foods:[‘娃娃菜‘,‘大白菜‘]},
    {name:‘肉类‘,foods:[‘猪肉‘,‘牛肉‘,]},
    {name:‘水果‘,foods:[‘苹果‘,‘西瓜‘]},
    {name:‘甜品‘,foods:[‘奶茶‘,‘华夫饼‘]},
],

相关DOM

左侧菜单栏

<div ref="leftMenu">
  <ul>
    <li
      v-for="(item, index) in foodList"     
      :key="index"
      :class="{ active: currentIndex === index }"
      @click="selectLeft(index)"
    >
      {{ item.name }}
    </li>
  </ul>
</div>
  • ref="leftMenu"获取左侧菜单栏的dom,用于创建滚动窗口
  • @click="selectLeft(index)"点击左侧菜单后触发,用于滑动到指定内容
  • :class="{ active: currentIndex === index }"动态改变样式

右侧内容栏

<div ref="rigntMenu" :style="‘height:‘ + scrollH + ‘px‘">
  <ul>
    <li v-for="(item, index) in foodList" 
        :key="index" 
        ref="rightItem">
      <span class="rightTitle">{{ item.name }}</span>
      <div
        v-for="(food, key) in item.foods"
        :key="key"
      >
		{{ food }}
      </div>
    </li>
  </ul>
</div>
  • ref="rigntMenu"获取右侧内容栏的dom,用于创建滚动窗口
  • ref="rightItem"获取某一品类的dom高度
  • :style="‘height:‘ + scrollH + ‘px‘"动态绑定固定容器的高度

函数与方法

创建滚动窗口

通过new Bscroll(对应dom,{相关配置})创建滚动窗口

scrollInit() {
    //创建左边菜单栏滚动窗口
    this.leftMenu = new Bscroll(this.$refs.leftMenu, {
        click: true,//允许点击
    });
    
    //创建右边内容栏滚动窗口
    this.rigntMenu = new Bscroll(this.$refs.rigntMenu, {
        probeType: 3, //在 rigntMenu 滚动时触发 scroll 事件
        click: true,
    });
    
    //当右侧滚动时,监听滚动距离,将滚动距离储存在scrollY中
    this.rigntMenu.on("scroll", (pos) => {
        this.scrollY = Math.abs(Math.round(pos.y));
    });
},

获取右侧项目高度

getListHeight(){
    const lis=this.$refs.rightItem   //获取每项的DOM
    this.heightList=[]	//储存每项的顶部位置
    let height=0  
    this.heightList.push(height)  //第一项的顶部垂直位置为0
    lis.map(item=>{
        height+=item.clientHeight //第二项顶部位置=第一项顶部位置+第二项的内容高度,以此类推
        this.heightList.push(height)
    })
},

右侧联动左侧

computed: {
    currentIndex() {
        //根据当前滚轮滑动的距离 判断左侧菜单现处位置
        const index = this.heightList.findIndex((item, index) => {
            return  (this.scrollY >= this.heightList[index] &&
                     this.scrollY < this.heightList[index + 1])
        });
        return index > 0 ? index : 0;
    },
},

左侧联动右侧

selectLeft(index) {
  let rightItem = this.$refs.rightItem; 
  let el = rightItem[index]; //根据索引获取对应dom
  this.rigntMenu.scrollToElement(el, 1000); //将右侧滚动窗口滚动至对应dom
},

初始化

mounted() {
   this.scrollH= window.innerHeight - 150
    this.$nextTick(() => {
        this.scrollInit()
        this.getLisHeight()
    })
}

如果是动态数据,下面的内容可以写在获取数据的函数内部的结尾。

this.$nextTick(() => {
    this.scrollInit()
    this.getLisHeight()
})

完整demo源码:https://github.com/sanhuamao1/menu-card/tree/master/src

评论(0
© 2014 mamicode.com 版权所有 京ICP备13008772号-2  联系我们:gaon5@hotmail.com
迷上了代码!