vue和better-scroll实现列表左右联动效果详解


Posted in Javascript onApril 29, 2019

一.实现思路

  1. (1)实现上是左右分别一个better-scroll列表
  2. (2)利用计算右侧列表每一个大区块的高度来计算左侧的位置

二.实现

1.实现左右两个better-scroll

(1)dom结构(better-scroll要求,会把最外层dom的第一个子元素作为要滚动的区域)

左边滚动列表dom
 <div class="menu-wrapper" v-el:menu-wrapper>
   <ul>
    <li v-for="item in goods" class="menu-item"
      :class="{'current':currentIndex === $index}"
      @click="selectMenu($index,$event)">
     <span class="text border-1px">
      <span v-show="item.type > 0" class="icon"
       :class="classMap[item.type]"></span>{{item.name}}
     </span>
    </li>
   </ul>
  </div>

右边滚动列表dom
<div class="food-wrapper" v-el:food-wrapper>
   <ul>
    <li v-for="item in goods" class="food-list food-list-hook">
     <h1 class="title">{{item.name}}</h1>
     <ul>
      <li v-for="food in item.foods" class="food-item border-1px">
       <div class="icon">
        <img width="57" height="57" :src="food.icon">
       </div>
       <div class="content">
        <h2 class="name">{{food.name}}</h2>
        <p class="desc">{{food.description}}</p>
        <div class="extra">
         <span class="count">月售{{food.sellCount}}份</span>
         <span>好评率{{food.rating}}%</span>
         <div class="price">
          <span class="now">¥{{food.price}}</span>
          <span class="old" v-show="food.oldPrice">¥{{food.oldPrice}}</span>
         </div>
        </div>
       </div>
      </li>
     </ul>
    </li>
   </ul>
  </div>

在数据请求完成后的$nextTick中初始化better-scroll,就能实现两个列表分别能滚动,至于联动,要后面自己做

_initScroll() {
    this.menuScroll = new BScroll(this.$els.menuWrapper,{
     click:true  //允许better-scroll列表上的点击事件
    });
    this.foodsScroll = new BScroll(this.$els.foodWrapper,{
     probeType : 3  //让better-scroll监听scroll事件
    });
    this.foodsScroll.on('scroll',(pos) => {
     this.scrollY =Math.abs(Math.round(pos.y));
    })
   },

2.实现联动效果

(1)具体的联动实现思路

  1. 在渲染完成后($nextTick内),初始化better-scroll,并在初始化函数内添加右侧列表的scroll监听事件,并记录scrollY值到,存入vue的data中
  2. 在渲染完成后($nextTick内),计算右侧列表的每一个大区块的高度,并累加,存入数组listHeight
  3. 因为scrollY值在滚动中总是不断变化的,所以在computed中计算出currentIndex,当前滚动区域是哪一个大区块,也就是listHeight数组的下标
  4. 在dom中根据currentIndex应用左侧列表被点中的样式
  5. 在左侧列表某一项被点中的时候,右侧列表滑动到某一个大块区域,
//初始化better-scroll
_initScroll() {
    this.menuScroll = new BScroll(this.$els.menuWrapper,{
     click:true
    });
    this.foodsScroll = new BScroll(this.$els.foodWrapper,{
     probeType : 3
    });
    this.foodsScroll.on('scroll',(pos) => {
     this.scrollY =Math.abs(Math.round(pos.y));
    })
   },
_calculateHeight() {
    let foodList = this.$els.foodWrapper.getElementsByClassName("food-list-hook");
    let height = 0;
    this.listHeight.push(height);
    for(let i=0;i<foodList.length;i++) {
     let item = foodList[i];
     height += item.clientHeight;
     this.listHeight.push(height);
    }
   }
computed: {
   currentIndex() {
    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)){
      return i;
     }
    }
    return 0;
   }
  },
<div class="menu-wrapper" v-el:menu-wrapper>
   <ul>
    <!-- :class="{'current':currentIndex === $index}" 就是根据currentIndex应用左侧列表被点中的样式 -->
    <li v-for="item in goods" class="menu-item"
      :class="{'current':currentIndex === $index}"
      @click="selectMenu($index,$event)">
     <span class="text border-1px">
      <span v-show="item.type > 0" class="icon"
       :class="classMap[item.type]"></span>{{item.name}}
     </span>
    </li>
   </ul>
  </div>
//被点击事件
//dom
<div class="menu-wrapper" v-el:menu-wrapper>
   <ul>
    <!-- @click="selectMenu($index,$event)" 就是点击事件 -->
    <li v-for="item in goods" class="menu-item"
      :class="{'current':currentIndex === $index}"
      @click="selectMenu($index,$event)">
     <span class="text border-1px">
      <span v-show="item.type > 0" class="icon"
       :class="classMap[item.type]"></span>{{item.name}}
     </span>
    </li>
   </ul>
  </div>
//js  
selectMenu(index,event) {
    if(!event._constructed) {
     return ;
    }
    let foodList = this.$els.foodWrapper.getElementsByClassName("food-list-hook");
    let el = foodList[index];
    this.foodsScroll.scrollToElement(el,300);
   },

以上所述是小编给大家介绍的vue和better-scroll实现列表左右联动效果详解整合,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
javascript add event remove event
Apr 07 Javascript
javascript fullscreen全屏实现代码
Apr 09 Javascript
鼠标拖拽移动子窗体的JS实现
Feb 25 Javascript
js中javascript:void(0) 真正含义
Nov 05 Javascript
实例解析jQuery中proxy()函数的用法
May 24 Javascript
JS实现根据文件字节数返回文件大小的方法
Aug 02 Javascript
vue.js组件之间传递数据的方法
Jul 10 Javascript
Vue Cli3 创建项目的方法步骤
Oct 15 Javascript
小程序获取周围IBeacon设备的方法
Oct 31 Javascript
javascript+HTML5 canvas绘制时钟功能示例
May 15 Javascript
JavaScript通如何过RGraph实现动态仪表盘
Oct 15 Javascript
原生JavaScript实现幻灯片效果
Feb 19 Javascript
Vue 引入AMap高德地图的实现代码
Apr 29 #Javascript
微信小程序--获取用户地理位置名称(无须用户授权)的方法
Apr 29 #Javascript
Vuejs学习笔记之使用指令v-model完成表单的数据双向绑定
Apr 29 #Javascript
微信小程序-form表单提交代码实例
Apr 29 #Javascript
vue在index.html中引入静态文件不生效问题及解决方法
Apr 29 #Javascript
微信小程序传值以及获取值方法的详解
Apr 29 #Javascript
小程序封装wx.request请求并创建接口管理文件的实现
Apr 29 #Javascript
You might like
PHP实现分页的一个示例
2006/10/09 PHP
PHP数组操作――获取数组最后一个值的方法
2015/04/14 PHP
PHP判断上传文件类型的解决办法
2015/10/20 PHP
PHP常用的三种设计模式汇总
2016/08/28 PHP
Win7环境下Apache连接MySQL提示连接已重置的解决办法
2017/05/09 PHP
php7 错误处理机制修改实例分析
2020/05/25 PHP
用javascript获得地址栏参数的两种方法
2006/11/08 Javascript
JXTree对象,读取外部xml文件数据,生成树的函数
2007/04/02 Javascript
原生js 秒表实现代码
2012/07/24 Javascript
jQuery学习笔记之toArray()
2014/06/09 Javascript
js图片跟随鼠标移动代码
2015/11/26 Javascript
理解Javascript图片预加载
2016/02/23 Javascript
JavaScript 判断一个对象{}是否为空对象的简单方法
2016/10/09 Javascript
基于javascript实现的快速排序
2016/12/02 Javascript
Angular.js与node.js项目里用cookie校验账户登录详解
2017/02/22 Javascript
整理关于Bootstrap过渡动画的慕课笔记
2017/03/29 Javascript
node.js文件上传重命名以及移动位置的示例代码
2018/01/19 Javascript
详解Vue-Router源码分析路由实现原理
2019/05/15 Javascript
Echarts地图添加引导线效果(labelLine)
2019/09/30 Javascript
Python中用PIL库批量给图片加上序号的教程
2015/05/06 Python
CSS3点击按钮实现背景渐变动画效果
2016/10/19 HTML / CSS
用html5的canvas画布绘制贝塞尔曲线完整代码
2013/08/14 HTML / CSS
美国儿童运动鞋和服装零售商:Kids Foot Locker
2017/08/05 全球购物
Sixt美国租车:高端豪华车型自驾体验
2017/09/02 全球购物
Parfume Klik丹麦:香水网上商店
2018/07/10 全球购物
日本最佳原创设计品牌:Felissimo(芬理希梦)
2019/03/19 全球购物
在对linux系统分区进行格式化时需要对磁盘簇(或i节点密度)的大小进行选择,请说明选择的原则
2012/01/13 面试题
毕业生个人的求职信范文
2013/12/03 职场文书
金融行业务员的自我评价
2013/12/13 职场文书
宿舍卫生检讨书
2014/01/16 职场文书
机械制造专业毕业生求职信
2014/03/02 职场文书
学生鉴定评语大全
2014/05/05 职场文书
销售顾问工作计划书
2014/09/15 职场文书
电气工程师岗位职责
2015/02/12 职场文书
荒岛余生观后感
2015/06/09 职场文书
Redis高并发缓存架构性能优化
2022/05/15 Redis