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 相关文章推荐
Cookie 小记
Apr 01 Javascript
jQuery下的几个你可能没用过的功能
Aug 29 Javascript
jquery获取checkbox的值并post提交
Jan 14 Javascript
JS实现横向与竖向两个选项卡Tab联动的方法
Sep 27 Javascript
javascript跨域总结之window.name实现的跨域数据传输
Nov 01 Javascript
jQuery1.9.1源码分析系列(十六)ajax之ajax框架
Dec 04 Javascript
jQuery中attr()与prop()函数用法实例详解(附用法区别)
Dec 29 Javascript
javascript中利用柯里化函数实现bind方法
Apr 29 Javascript
jq给页面添加覆盖层遮罩的实例
Feb 16 Javascript
canvas绘制环形进度条
Feb 23 Javascript
jQuery中的$是什么意思及 $. 和 $().的区别
Apr 20 jQuery
微信小程序地图(map)组件点击(tap)获取经纬度的方法
Jan 10 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
destoon首页调用求购供应信息的地区名称的方法
2014/08/21 PHP
php获取当前页面完整URL地址
2015/12/30 PHP
用HTML/JS/PHP方式实现页面延时跳转的简单实例
2016/07/18 PHP
TP(thinkPHP)框架多层控制器和多级控制器的使用示例
2018/06/13 PHP
PHP convert_cyr_string()函数讲解
2019/02/13 PHP
Yii框架getter与setter方法功能与用法分析
2019/10/22 PHP
解决jquery插件冲突的问题
2014/01/23 Javascript
c#+jquery实现获取radio和checkbox的值
2020/09/12 Javascript
利用jquery获取select下拉框的值
2016/11/23 Javascript
vue-resource 拦截器使用详解
2017/02/21 Javascript
PHP实现本地图片上传和验证功能
2017/02/27 Javascript
Vue打包后出现一些map文件的解决方法
2018/02/13 Javascript
vue左侧菜单,树形图递归实现代码
2018/08/24 Javascript
如何为vuex实现带参数的 getter和state.commit
2019/01/04 Javascript
基于JS实现web端录音与播放功能
2019/04/17 Javascript
JavaScript动态检测密码强度原理及实现方法详解
2019/06/11 Javascript
layui-tree实现Ajax异步请求后动态添加节点的方法
2019/09/23 Javascript
JS数组splice操作实例分析
2019/10/12 Javascript
node事件循环和process模块实例分析
2020/02/14 Javascript
[08:07]DOTA2每周TOP10 精彩击杀集锦vol.8
2014/06/25 DOTA
[00:36]DOTA2上海特级锦标赛 Archon战队宣传片
2016/03/04 DOTA
python实现雨滴下落到地面效果
2018/06/21 Python
python获取微信小程序手机号并绑定遇到的坑
2018/11/19 Python
基于python3 的百度图片下载器的实现代码
2019/11/05 Python
基于Python计算圆周率pi代码实例
2020/03/25 Python
python如何爬取网页中的文字
2020/07/28 Python
HTML5 Canvas实现烟花绽放特效
2016/03/02 HTML / CSS
Debenhams爱尔兰:英国知名的百货公司
2017/01/02 全球购物
Mio Skincare法国官网:身体紧致及孕期身体护理
2018/04/04 全球购物
美国婴儿和儿童服装购物网站:PatPat
2020/10/01 全球购物
社区十八大感言
2014/01/19 职场文书
教师师德承诺书
2014/03/26 职场文书
教师节简报
2015/07/20 职场文书
诗词赏析-(浣溪沙)
2019/08/13 职场文书
Python进度条的使用
2021/05/17 Python