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 相关文章推荐
jquery下将选择的checkbox的id组成字符串的方法
Nov 28 Javascript
基于jquery的下拉框改变动态添加和删除表格实现代码
Sep 12 Javascript
js动态添加事件并可传参数示例代码
Oct 21 Javascript
基于jquery实现的图片在各种分辨率下未知的容器内上下左右居中
May 11 Javascript
JS实现的简单鼠标跟随DiV层效果完整实例
Oct 31 Javascript
JavaScript文档碎片操作实例分析
Dec 12 Javascript
理解JavaScript表单的基础知识
Jan 25 Javascript
jquery判断checkbox是否选中及改变checkbox状态的实现方法
May 26 Javascript
AngularJS路由删除#符号解决的办法
Sep 28 Javascript
微信小程序左滑动显示菜单功能的实现
Jun 14 Javascript
如何基于javascript实现贪吃蛇游戏
Feb 09 Javascript
微信小程序实现自定义动画弹框/提示框的方法实例
Nov 06 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 生成文字png图片的代码
2011/04/17 PHP
PHP使用memcache缓存技术提高响应速度的方法
2014/12/26 PHP
php实现粘贴截图并完成上传功能
2015/05/17 PHP
php array_keys 返回数组的键名
2016/10/25 PHP
基于jquery循环map功能的代码
2011/02/26 Javascript
JS获取整个页面文档的实现代码
2011/12/15 Javascript
利用javascript解决图片缩放及其优化的代码
2012/05/23 Javascript
nodejs教程 安装express及配置app.js文件的详细步骤
2013/05/11 NodeJs
JavaScript中的函数重载深入理解
2014/08/04 Javascript
js使用split函数按照多个字符对字符串进行分割的方法
2015/03/20 Javascript
js如何实现点击标签文字,文字在文本框出现
2015/08/05 Javascript
JS+CSS简单树形菜单实现方法
2015/09/12 Javascript
如何解决easyui自定义标签 datagrid edit combobox 手动输入保存不上
2015/12/26 Javascript
基于javascript实现根据身份证号码识别性别和年龄
2016/01/22 Javascript
多种js图片预加载实现方式分享
2016/02/19 Javascript
vue计算属性get和set用法示例
2019/02/08 Javascript
js实现无缝滚动双图切换效果
2019/07/09 Javascript
python中快速进行多个字符替换的方法小结
2016/12/15 Python
python实现公司年会抽奖程序
2019/01/22 Python
Python读取Pickle文件信息并计算与当前时间间隔的方法分析
2019/01/30 Python
python机器人运动范围问题的解答
2019/04/29 Python
python框架flask入门之环境搭建及开启调试
2020/06/07 Python
python 读取串口数据的示例
2020/11/09 Python
纯html5+css3下拉导航菜单实现代码
2013/03/18 HTML / CSS
HTML5 3D书本翻页动画的实现示例
2019/08/28 HTML / CSS
阿迪达斯比利时官方商城:adidas比利时
2016/10/10 全球购物
美国药妆网站:EDCskincare.com(防晒、痤疮、抗衰老等)
2017/04/28 全球购物
捷克浴室和厨房设备购物网站:SIKO
2018/08/11 全球购物
英国领先的名牌服装折扣零售商:Brown Bag Clothing
2019/01/08 全球购物
党员的自我评价范文
2014/01/02 职场文书
房地产营销策划方案
2014/02/08 职场文书
司法局群众路线教育实践活动整改措施思想汇报
2014/10/13 职场文书
大学生村官工作心得体会
2016/01/23 职场文书
Javascript中的解构赋值语法详解
2021/04/02 Javascript
jquery插件实现代码雨特效
2021/04/24 jQuery
深入理解CSS 中 transform matrix矩阵变换问题
2021/08/30 HTML / CSS