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.autocomplete修改实现键盘上下键自动填充示例
Nov 19 Javascript
js document.write()使用介绍
Feb 21 Javascript
javascript中的事件代理初探
Mar 08 Javascript
jQuery动画与特效详解
Feb 01 Javascript
jQuery插件制作之全局函数用法实例
Jun 01 Javascript
关于不同页面之间实现参数传递的几种方式讨论
Feb 13 Javascript
JavaScript实现焦点进入文本框内关闭输入法的核心代码
Sep 20 Javascript
使用vuex的state状态对象的5种方式
Apr 19 Javascript
Element输入框带历史查询记录的实现示例
Jan 15 Javascript
详解Vue中的基本语法和常用指令
Jul 23 Javascript
使用Node.js实现base64和png文件相互转换的方法
Mar 11 Javascript
详解vue-router的导航钩子(导航守卫)
Nov 02 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
优化NFR之一 --MSSQL Hello Buffer Overflow
2006/10/09 PHP
PHP合并两个数组的两种方式的异同
2012/09/14 PHP
php 验证码(倾斜,正弦干扰线,黏贴,旋转)
2013/06/29 PHP
PHP修改session_id示例代码
2014/01/08 PHP
php在apache环境下实现gzip配置方法
2015/04/02 PHP
php+mysql实现简单登录注册修改密码网页
2016/11/30 PHP
php单元测试phpunit入门实例教程
2017/11/17 PHP
php/JS实现的生成随机密码(验证码)功能示例
2019/06/06 PHP
PHP实现笛卡尔积算法的实例讲解
2019/12/22 PHP
Javascript 获取LI里的内容
2008/12/17 Javascript
textarea中的手动换行处理的jquery代码
2011/02/26 Javascript
Prototype源码浅析 String部分(一)之有关indexOf优化
2012/01/15 Javascript
node.js中的fs.mkdir方法使用说明
2014/12/17 Javascript
js图片模糊切换显示特效的方法
2015/02/17 Javascript
JavaScript调用浏览器打印功能实例分析
2015/07/17 Javascript
BootStrap文件上传样式超好看【持续更新】
2016/05/10 Javascript
ES6所改良的javascript“缺陷”问题
2016/08/23 Javascript
JavaScript获取tr td 的三种方式全面总结(推荐)
2017/08/15 Javascript
angular2路由之routerLinkActive指令【推荐】
2018/05/30 Javascript
jQuery操作元素的内容和样式完整实例分析
2020/01/10 jQuery
Python 学习笔记
2008/12/27 Python
Python对HTML转义字符进行反转义的实现方法
2019/04/28 Python
Python通过Pillow实现图片对比
2020/04/29 Python
python读取hdfs上的parquet文件方式
2020/06/06 Python
pytorch 常用函数 max ,eq说明
2020/06/28 Python
比利时的在线灯具店:Lampen24.be
2019/07/01 全球购物
static函数与普通函数有什么区别
2015/12/25 面试题
生产车间班组长岗位职责
2014/01/06 职场文书
《在家里》教后反思
2014/03/01 职场文书
财务部副经理岗位职责
2014/03/14 职场文书
电子信息工程专业自荐书
2014/06/24 职场文书
实验室安全管理制度
2015/08/05 职场文书
pandas:get_dummies()与pd.factorize()的用法及区别说明
2021/05/21 Python
实操Python爬取觅知网素材图片示例
2021/11/27 Python
微信小程序中使用vant框架的具体步骤
2022/02/18 Javascript
Android中View.post和Handler.post的关系
2022/06/05 Java/Android