欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

vue 饿了么菜单左右联动

程序员文章站 2023-12-31 16:26:52
...

最近写了一个小demo ,饿了么菜单左右联动效果,由于公司的后台太差劲,到现在还没有给我接口文档,就用本地数据写了一下,写得注释超级详细 ,主要是点击左侧右侧可以滑动到指定位置,滑动右侧左侧联动效果,回弹动画效果,别的还没有写,直接上代码 有需要改进的地方,欢迎各位提出宝贵的意见
基于better-scroll 做的 首先需要下载

npm install better-scroll --save
<template>
  <div class="goods">
     <div class="menu-wrapper" ref="menuWrapper">
       <ul>
         <li v-for="(item,index) in goods" class="menu-item" :class="{current: currentIndex === index}" @click="selectMenu(index)" :key="index">
           <span class="text border-1px">{{item.name}}</span>
         </li>
       </ul>
     </div>
     <div class="foods-wrapper" ref="foodsWrapper">
       <ul>
         <li v-for="item in goods" class="food-list food-list-hook" :key="item.id">
           <h1 class="title">{{item.name}}</h1>
           <ul v-for="food in item.foods" class="food-item border-1px" :key="food.id">
             <div class="icon" @click="selectFood(food)">
               <img width="57" height="57" :src="food.icon">
             </div>
             <div class="content">
               <h2 class="name">{{food.name}}</h2>
               <p class="description">{{food.description}}</p>
               <div class="extra">
                 <span class="count">月售{{food.sellCount}}</span><span class="rating">好评率{{food.rating}}%</span>
               </div>
               <div class="price">
                 <span class="now">{{food.price}}</span><span v-show="food.oldPrice" class="old">{{food.oldPrice}}</span>
               </div>
               
               <div class="cart-wrapper">
               
               </div>
             </div>
           </ul>
         </li>
       </ul>
     </div>
  </div>
</template>

<script>
import BScroll from 'better-scroll'
import Datas from '../../common/json/data'
export default {
  
  data () {
    return {
      goods: [],
      listHeight: [],
      scrollY: 0,
     
    }
  },
  computed: {
    // 计算得到当前分类下标
    currentIndex () {
    //第一种写法 有点繁琐 不推荐
    //   for (let i = 0; i < this.listHeight.length; i++) {
    //     let height1 = this.listHeight[i]
    //     let height2 = this.listHeight[i + 1]
    //     if (!height2 || (this.scrollY >= height1 && this.scrollY < height2)) {
    //       return i
    //     }
    //   }
    //   return 0
        //  解构赋值 
      
    // 第二种写法已改进   根据条件计算 产生一个结果 findIndex查找满足条件的下标 没找到返回-1
      const index=this.listHeight.findIndex((item,index)=>{
        //   如果滚动的距离>=左侧列表当前的高度并且 小于下一项的高度 
          return this.scrollY>=item && this.scrollY<this.listHeight[index + 1]
      })
     
        return index
    },
  },
  created () {
  this.goods=Datas.goods
  
  },
  mounted () {
    //   这里用到一个定时器 等待数据渲染完毕 执行该方法 不然不能滑动 如果是真实数据 这两个方法放在this.$nextTick()里面
    //因为没有真实数据 只能用本地数据模拟下
    setTimeout(() => {
      this._initScroll()
      this._calculateHeight()
    }, 20)
  },
  methods: {
        //     设置两边列表可以滚动  内容区要比外层容器要高  列表先渲染 才可以滑动 
    _initScroll () {
        
      this.menuScroll = new BScroll(this.$refs.menuWrapper, {
        click: true
      })
      this.foodsScroll = new BScroll(this.$refs.foodsWrapper, {
        click: true,
        probeType: 2
      })
    //    右侧表绑定滑动监听 
      this.foodsScroll.on('scroll', (pos) => {
        //  获取每次滚动的值 绝对值
        this.scrollY = Math.abs(Math.round(pos.y))
      })
      //  右侧列表绑定滑动结束监听
      this.foodsScroll.on('scrollEnd', (pos) => {
        this.scrollY = Math.abs(Math.round(pos.y))
        console.log(this.scrollY)
      })
    },
    
          
    _calculateHeight () {
        // 获取 所有左侧列表li  class 为 food-list-hook ul设置ref 
      let foodList = this.$refs.foodsWrapper.getElementsByClassName('food-list-hook')

          let height=0;
          this.listHeight.push(height)
      // 第一种写法 有点繁琐 不推荐 
        //  定义初始值 li可见高度为 0  
    //   let height = 0
    // //   初始值0 添加到listHeight数组
    //   this.listHeight.push(height)
    // //   循环遍历所有左侧列表 得到所有li可视区域高度 
    //   for (let i = 0; i < foodList.length; i++) {
    //     let item = foodList[i]
    //         // 高度+= 左侧列表当前项的可视高度
    //     height += item.clientHeight
    //     //  收集左侧列表所有li可见区域高度
    //     this.listHeight.push(height)
    //   }

        // 第二种写法以改进  伪数组转为真数组 并循环遍历
          Array.prototype.slice.call(foodList).forEach((i) =>{
               height += i.clientHeight
                 this.listHeight.push(height)
          })
    
    },
    //  点击左侧列表 右侧列表滑动到指定位置
    selectMenu (index) {
    
      let foodList = this.$refs.foodsWrapper.getElementsByClassName('food-list-hook')
    //   scrollToElement可以滑动到指定位置
      this.foodsScroll.scrollToElement(foodList[index],300)
    //    第一个参数对应的食品列表 
    //  第二个参数为滑动 动画时长
    },
  
  }
  
}
</script>

<style lang="scss" scoped>
    .goods{
    position: absolute;
    top: 176px;
    bottom: 44px;
    width: 100%;
    max-width: 540px;
    display: flex;
    overflow: hidden;
    .menu-wrapper{
    flex: 0 0 80px;
    background: #f3f5f7;
    }
    }
    .menu-item{
    width: 56px;
    height: 54px;
    display: table;
    font-size: 12px;
    line-height: 14px;
    padding: 0 12px;
    font-weight: 200;
    &:last-child{
    .text:after{
    border-top: none;
    }          
    }
    &.current{
    position: relative;
    background: #fff;
    font-weight: 700;
    margin-top: -1px;
    color: aquamarine;
    z-index: 100;
    .text:after{
    border-top: 0;
    }           
    }
    .text{
    display: table-cell;
    vertical-align: middle;
    width: 56px;
    font-size: 12px;   
    .icon{
    vertical-align: top;
    display: inline-block;
    width: 12px;
    height: 12px;
    margin-right: 4px;
    background-size: 12px 12px;
    background-repeat: no-repeat;
    }
    }  
    }
    .foods-wrapper{
    flex: 1;
    .title{
    border-left: 2px solid #d9dde1;
    font-size: 12px;
    width: 420px;
    height: 26px;
    line-height: 26px;
    padding-left: 10px;
    margin-left: 12PX;
    background:#f0f0f0;
    color: rgb(147,153,159);
    p{
    background-color: #f3f5f7;
    }
    }      
        
    .food-item{
    display: flex;
    margin: 18px;
    padding-bottom: 18px;
    border:rgba(7,17,27,.1) 1PX solid;
    &:last-child:after{
        border-top: 0;
    }
            
    .icon{
    flex: 0 0 57px;
    margin-right: 10px;
    }
    .content{
        flex: 1;
    }       
    .name{
    margin: 2px 0 8px 0;
    line-height: 14px;
    font-size: 14px;
    color: rgb(7,17,27);
    }                  
    .description,.extra{
    font-size: 10px ;
        line-height: 10px;
        color: rgb(147,153,159);
        margin-bottom: 8px;         
    }         
    .extra{
    .count{
    margin-right: 12px;
    line-height: 10px;
    }
    }      
    .rating{
    line-height: 10px;
    }        
    .price{
    .now{
    font-size: 14px;
    color: rgb(240,20,20);
    font-weight: 700;
    line-height: 24px;
    margin-right: 8px;
    }
    }                   
    .old{
        font-size: 10px;
        text-decoration: line-through;
        color: rgb(147,153,159);
        font-weight: 700;
        line-height: 24px;
        }          
        .cart-wrapper{
            position: absolute;
            right: 0;
            bottom: 12px;
            }
        }
        }                            
</style>

不知道咋个搞那种效果动图,那个会可以教下我么。。。。。
vue 饿了么菜单左右联动

上一篇:

下一篇: