Vue项目中使用better-scroll实现菜单映射功能方法


Posted in Javascript onSeptember 11, 2019

组件全部代码

<template>

<div class="goods">
  <!--左侧区域-->
  <div class="menu-wrapper" ref="left">
    <ul class="menu">
      <li class="menu-item border-bottom"
        :class="{'current':currentIndex===index}"
        v-for="(item,index) in dataLlist.goods"
        :key="index"
        @click="selectIndex(index,$event)"
        ref="menuList"
      >
        <div class="text">
          <goods-icon v-show="item.type>0" :index="item.type" class="text-ico"></goods-icon>
          {{item.name}}
        </div>
      </li>
    </ul>
  </div>
  <!--右侧区域-->
  <div class="foods-wrapper" ref="right">
    <ul>
      <li class="food-list food-list-hook"
        v-for="(item,index) in dataLlist.goods"
        :key="index">
        <!--标题区域-->
        <h1 class="border-left">{{item.name}}</h1>
        <ul>
          <li class="food-item border-bottom"
            v-for="(foodItem,index) in item.foods"
          >
            <div class="food-image">
              <img :src="foodItem.icon" alt="foodItem.name">
            </div>
            <div class="food-desc">
              <div class="title">{{foodItem.name}}</div>
              <div class="desc">{{foodItem.description}}</div>
              <div class="num">
                <div class="sellCount">月售{{foodItem.sellCount}}份</div>
                <div class="rating">好评率{{foodItem.rating}}%</div>
              </div>
              <div class="price">
                <div class="new-price">¥{{foodItem.price}}</div>
                <div class="old-price border-bottom" v-show="foodItem.oldPrice">¥{{foodItem.oldPrice}}</div>
              </div>
            </div>

          </li>
        </ul>
      </li>
    </ul>
  </div>
</div>
</template>

<script>

import Icon from '../../common/iconType/Icon';
import BScroll from 'better-scroll'

export default {
  name: "Goods",
  props:['dataLlist'],
  data(){
    return{
      listHeight:[],
      scrollY:0 ,//为了实现左右区域映射
    }
  },
  computed:{
    currentIndex(){ //这个返回的是下标,当这个currentIndex的值与goods的下标一致的时候,
      // 左侧区域就会呈现高亮现象
      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)) {
          this._followScroll(i) //实现当滑动的时候,左侧隐藏的食物类型显示
          return i;
        }
      }
      return 0;
    }
  },
  created(){
    //dataLlist数据是异步加载,直接用new BScroll时,dom可能还没有更新
    this.$nextTick(()=>{ //this.$nextTick()将回调延迟到下次 DOM 更新循环之后执行,使用$nextTick异步初始化Bscroll
      this.meunScroll=new BScroll(this.$refs.left,{
        click:true
      });
      this.foodScroll=new BScroll(this.$refs.right,{
        probeType: 3 //可以派发scroll事件,检测到实时滚动的位置
      });
      this.foodScroll.on('scroll',(pos) =>{
        //参数pos就是在右侧区域滑动的实时位置
        //Math.round()取整数,Math.abs取绝对值
        this.scrollY =Math.abs( Math.round(pos.y));
      });
      this._calculateHeight(); //这个方法为了获取每个商品类的最大区间的高度
    })
  },
  methods:{
    _followScroll(index) {
      if(index > 0 ){
        let menuList = this.$refs.menuList;
        let el = menuList[index];
        this.meunScroll.scrollToElement(el, 300, 0, -100);//better-scroll的scrollToElement方法滚动到指定位置
      }
      },
    _calculateHeight(){ //这个方法为了获取每个商品类的最大区间的高度
     let height = 0;
     let foodLsit = this.$refs.right.getElementsByClassName('food-list-hook');
     this.listHeight.push(height); //listHeight这个数组是用来存放右侧商品中每个类型商品的最大区间高度的集合
     for(var i=0;i<foodLsit.length;i++){
       let item = foodLsit[i];
       //clientHeight代表元素的高度
       height += item.clientHeight; //每个元素的高度等于自身高度加上上一个元素的高度
       this.listHeight.push(height); //最终listHeight集合了所有li[类为food-list-hook]到最顶部的高度
     }
    },
    selectIndex(index,ele){
      //better-scroll 会禁止移动端的点击事件,需要重新派发,同时在PC端会点击两次,此处需要做判断
      if(!ele._constructed){
        //better-scroll的派发事件scroll的event和pc端浏览器的点击事件的event有个
        // 属性区别_constructed,pc端浏览器的点击事件的event中是没有这个属性的
        return;
      }
      let rightItem =this.$refs.right.getElementsByClassName('food-list-hook');
      let item = rightItem[index]; //找到相应的li
      this.foodScroll.scrollToElement(item, 250) //better-scroll的scrollToElement方法滚动到指定位置
    }
   // scrollToElement(el, time, offsetX, offsetY, easing) //第一个值接收目标元素,第二个是滚动时间,第三第四个是相对于目标元素的偏移量。
},

  components:{
    'goods-icon': Icon
  }

}
</script>

<style scoped lang="stylus">

@import "../../assets/stylus/mixin.styl"
.goods

position absolute
top 3.6rem
bottom .92rem
display flex
width: 100%
overflow: hidden
.menu-wrapper
  flex 0 0 1.6rem
  width 1.6rem
  background-color #f3f5f7
  .menu-item
    height 1.08rem
    display flex
    align-items center
    justify-content left
    &.border-bottom::before
       color rgba(7,17,27,.1)
    .text
      font-weight 200
      font-size .24rem
      line-height .28rem
      margin 0 .24rem
      .text-ico
         margin-right -.08rem
         vertical-align top;
    &.current
      font-size .24rem
      line-height .28rem
      color rgb(240,20,20)
      background-color #ffffff
.foods-wrapper
  flex 1
  .food-list
    h1
      width 100%
      height .52rem
      line-height .52rem
      padding-left .28rem
      background-color #f3f5f7
      font-size .24rem
      color rgb(147,153,159)
      &.border-left::before
        border-color #d9dde1
        border-width .1rem


    .food-item
      display flex
      padding .36rem
      &:last-child.border-bottom
        border none
      .food-desc
        margin-left .2rem
        font-size .2rem
        color rgb(147,153,159)
        .title
          font-size:.28rem
          color rgb(7,17,27)
          margin-top .04rem
          line-height .28rem
        .desc
          margin .15rem auto
          line-height:.28rem
        .num
          display flex
          margin 0 0 .16rem 0
          .sellCount
             margin-right .24rem

        .price
          display flex
          align-items center
          .new-price
            color rgb(220,20,60)
            font-weight 700
            line-height .48rem
            margin-right .16rem
            font-size .28rem

          .old-price
            &.border-bottom::before
              position absolute
              top: 25%;
              border-width: 0.08rem;

</style>

Vue项目中使用better-scroll实现菜单滑动功能

安装和在组件中引入better-scroll

npm install better-scroll --save

引入import BScroll from 'better-scroll' 【在组件中引入,在后续的export default中就可以直接使用封装好的better-scroll功能了】

better-scroll实现的下面功能

在菜单中要实现点击左侧菜单的食品类型名称,右侧就会自动滑动到此食品类型下的所有食品;在右侧区域中滑动到食品类型下的所有食品区域下的时候,左侧菜单会出现相应的高亮效果

如何实现上面的功能:

第一:需要知道要在哪些区域间实现滑动

Vue项目中使用better-scroll实现菜单映射功能方法

第二:通过new BScroll()获取要实现滑动的区域

this.meunScroll=new BScroll(this.$refs.left);
this.foodScroll=new BScroll(this.$refs.right);

第三:上面代码在理论上应该在相应的区域都应该能滑动了,但是现实是并不能滑动

原因是:数据的获取是异步获取的,在定义滑动区域的时候,也许数据还没有更新,这是this.meunScroll的高度可能就没有高度外部类goods的高度,这样就不会滑动。

解决的方法:this.$nextTick()将回调延迟到下次 DOM 更新循环之后执行,使用$nextTick异步初始化Bscroll

this.$nextTick(()=>{ //this.$nextTick()将回调延迟到下次 DOM 更新循环之后执行,使用$nextTick异步初始化Bscroll
      this.meunScroll=new BScroll(this.$refs.left,{
        click:true //左侧菜单可以进行点击事件
      });
      this.foodScroll=new BScroll(this.$refs.right,{
        probeType: 3 //可以派发scroll事件,检测到实时滚动的位置
      });
      【this.foodScroll中必须有 probeType: 3后才能进行下面的scroll事件】
      this.foodScroll.on('scroll',(pos) =>{
        //参数pos就是在右侧区域滑动的实时位置
        //Math.round()取整数,Math.abs取绝对值
        this.scrollY =Math.abs( Math.round(pos.y));
      });
      this._calculateHeight(); //这个方法为了获取每个商品类的最大区间的高度
    })

获取每个右侧区域的 <li class="food-list food-list-hook">的高度

在data中定义一个空listHeight数组;数组中的元素代表了每个li到this.foodScroll最顶部的区域高度;

_calculateHeight(){ //这个方法为了获取每个商品类的最大区间的高度

let height = 0;
     let foodLsit = this.$refs.right.getElementsByClassName('food-list-hook');
     this.listHeight.push(height); //listHeight这个数组是用来存放右侧商品中每个类型商品的最大区间高度的集合
     for(var i=0;i<foodLsit.length;i++){
       let item = foodLsit[i];
       //clientHeight代表元素的高度
       height += item.clientHeight; //每个元素的高度等于自身高度加上上一个元素的高度
       this.listHeight.push(height); //最终listHeight集合了所有li[类为food-list-hook]到最顶部的高度
     }
    },
let foodLsit = this.$refs.right.getElementsByClassName('food-list-hook');

foodLsit表示所有li【 <li class="food-list food-list-hook">】dom集合;

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
Javascript 遍历对象中的子对象
Jul 03 Javascript
解决jquery .ajax 在IE下卡死问题的解决方法
Oct 26 Javascript
加载jQuery后$冲突的解决办法
Jul 09 Javascript
jquery仿搜索自动联想功能代码
May 23 Javascript
js实现字符串转日期格式的方法
May 20 Javascript
jquery使整个div区域可以点击的方法
Jun 24 Javascript
javascript实现页面刷新时自动清空表单并选中的方法
Jul 18 Javascript
JQuery中Ajax()的data参数类型实例分析
Dec 15 Javascript
在vue.js中抽出公共代码的方法示例
Jun 08 Javascript
Electron-vue脚手架改造vue项目的方法
Oct 22 Javascript
jquery实现动态添加附件功能
Oct 23 jQuery
vue-cli2 构建速度优化的实现方法
Jan 08 Javascript
使用layui+ajax实现简单的菜单权限管理及排序的方法
Sep 10 #Javascript
修改layui的后台模板的左侧导航栏可以伸缩的方法
Sep 10 #Javascript
layui固定下拉框的显示条数(有滚动条)的方法
Sep 10 #Javascript
使用layui实现的左侧菜单栏以及动态操作tab项方法
Sep 10 #Javascript
浅谈监听单选框radio改变事件(和layui中单选按钮改变事件)
Sep 10 #Javascript
layui给下拉框、按钮状态、时间赋初始值的方法
Sep 10 #Javascript
微信提示 在浏览器打开 效果实现过程解析
Sep 10 #Javascript
You might like
全面解读PHP的人气开发框架Laravel
2015/10/15 PHP
php实现推荐功能的简单实例
2019/09/29 PHP
JavaScript 捕获窗口关闭事件
2009/07/26 Javascript
HTA版JSMin(省略修饰语若干)基于javascript语言编写
2009/12/24 Javascript
js格式化货币数据实现代码
2013/09/04 Javascript
thinkphp 表名 大小写 窍门
2015/02/01 Javascript
JavaScript数组对象赋值用法实例
2015/08/04 Javascript
JS使用post提交的两种方式
2015/12/03 Javascript
javascript设置页面背景色及背景图片的方法
2015/12/29 Javascript
vue.js初学入门教程(1)
2016/11/03 Javascript
vue.js指令v-model实现方法
2016/12/05 Javascript
Javascript实现倒计时时差效果
2017/05/18 Javascript
js 开发之autocomplete=&quot;off&quot;在chrom中失效的解决办法
2017/09/28 Javascript
jQuery实现鼠标移到某个对象时弹出显示层功能
2018/08/23 jQuery
微信小程序使用gitee进行版本管理
2018/09/20 Javascript
vuejs router history 配置到iis的方法
2018/09/20 Javascript
vue项目部署到nginx/tomcat服务器的实现
2019/08/26 Javascript
js实现图片区域可点击大小随意改变(适用移动端)代码实例
2019/09/11 Javascript
[51:15]2014 DOTA2国际邀请赛中国区预选赛 Orenda VS LGD-GAMING
2014/05/22 DOTA
Python实现的数据结构与算法之双端队列详解
2015/04/22 Python
python 获取一个值在某个区间的指定倍数的值方法
2018/11/12 Python
一篇文章搞懂Python的类与对象名称空间
2018/12/10 Python
python中的数据结构比较
2019/05/13 Python
Python 程序报错崩溃后如何倒回到崩溃的位置(推荐)
2020/06/23 Python
Python LMDB库的使用示例
2021/02/14 Python
css3使网页、图片变成灰色兼容大多数浏览器
2014/07/02 HTML / CSS
高中生自我评价个人范文
2013/11/09 职场文书
法学院方阵解说词
2014/01/29 职场文书
2013年军训通讯稿
2014/02/05 职场文书
老师的检讨书
2014/02/23 职场文书
教师中国梦演讲稿
2014/04/23 职场文书
餐饮商业计划书范文
2014/04/29 职场文书
幼儿园户外活动总结
2014/07/04 职场文书
三好学生评语大全
2014/12/29 职场文书
SpringCloud Feign请求头删除修改的操作代码
2022/03/20 Java/Android
Spring中的@Transactional的工作原理
2022/06/05 Java/Android