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 相关文章推荐
JavaScipt基本教程之JavaScript语言的基础
Jan 16 Javascript
js实现连续英文字符自动换行兼容ie6 ie7和firefox
Sep 06 Javascript
js 剪切板应用clipboardData详细解析
Dec 17 Javascript
jq实现酷炫的鼠标经过图片翻滚效果
Mar 12 Javascript
javascript常见数据验证插件大全
Aug 03 Javascript
浅谈javascript中new操作符的原理
Jun 07 Javascript
深入浅析JavaScript的API设计原则
Jun 14 Javascript
微信小程序 小程序制作及动画(animation样式)详解
Jan 06 Javascript
js中常用的Math方法总结
Jan 12 Javascript
mui 打开新窗口的方式总结及注意事项
Aug 20 Javascript
基于JS实现html中placeholder属性提示文字效果示例
Apr 19 Javascript
浅谈vue项目,访问路径#号的问题
Aug 14 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
新52大事件
2020/03/03 欧美动漫
PHP集成百度Ueditor 1.4.3
2014/11/23 PHP
浅谈php7的重大新特性
2015/10/23 PHP
WordPress中创建用户角色的相关PHP函数使用详解
2015/12/25 PHP
JQuery this 和 $(this) 的区别
2009/08/23 Javascript
层序遍历在ExtJs的TreePanel中的应用
2009/10/16 Javascript
在页面上用action传递参数到后台出现乱码的解决方法
2013/12/31 Javascript
网站繁简切换的JS遇到页面卡死的解决方法
2014/03/12 Javascript
js 动态为textbox添加下拉框数据源的方法
2014/04/24 Javascript
JavaScript实现把rgb颜色转换成16进制颜色的方法
2015/06/01 Javascript
初步认识JavaScript函数库jQuery
2015/06/18 Javascript
JavaScript中Object.prototype.toString方法的原理
2016/02/24 Javascript
AngularJS 所有版本下载地址
2016/09/14 Javascript
js获取地址栏中传递的参数(两种方法)
2017/02/08 Javascript
Node.js 使用递归实现遍历文件夹中所有文件
2017/09/18 Javascript
详解如何为你的angular app构建一个第三方库
2018/12/07 Javascript
微信小程序实现单列下拉菜单效果
2019/04/25 Javascript
JavaScript Array.flat()函数用法解析
2020/09/02 Javascript
[06:16]第十四期-国士无双绝地翻盘之撼地神牛
2014/06/24 DOTA
用Python编程实现语音控制电脑
2014/04/01 Python
Python数据分析matplotlib设置多个子图的间距方法
2018/08/03 Python
Python:Numpy 求平均向量的实例
2019/06/29 Python
Pytorch实现GoogLeNet的方法
2019/08/18 Python
Python 3.6打包成EXE可执行程序的实现
2019/10/18 Python
python redis存入字典序列化存储教程
2020/07/16 Python
python 服务器运行代码报错ModuleNotFoundError的解决办法
2020/09/16 Python
Restful_framework视图组件代码实例解析
2020/11/17 Python
如何用python爬取微博热搜数据并保存
2021/02/20 Python
Stutterheim瑞典:瑞典高级外套时装品牌
2019/06/24 全球购物
大学生大二自我鉴定
2013/10/28 职场文书
实习自我评价怎么写
2013/12/02 职场文书
新闻专业个人求职信
2013/12/19 职场文书
我的梦想演讲稿1000字
2014/08/21 职场文书
勇敢的心观后感
2015/06/09 职场文书
英文投诉信格式
2015/07/03 职场文书
2015年中秋节主持词
2015/07/30 职场文书