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 相关文章推荐
jQuery get和post 方法传值注意事项
Nov 03 Javascript
Javascript获取统一管理的提示语(message)
Feb 03 Javascript
angular.js分页代码的实例
Jul 27 Javascript
jquery网页加载进度条的实现
Jun 01 jQuery
jQuery动画_动力节点节点Java学院整理
Jul 04 jQuery
详解使用nvm安装node.js
Jul 18 Javascript
Vue2.0用 watch 观察 prop 变化(不触发)
Sep 08 Javascript
Node 升级到最新稳定版的方法分享
May 17 Javascript
js replace 全局替换的操作方法
Jun 12 Javascript
Vue中控制v-for循环次数的实现方法
Sep 26 Javascript
基于vue实现移动端圆形旋钮插件效果
Nov 28 Javascript
深入理解Vue.js轻量高效的前端组件化方案
Dec 10 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和ASP.NET的10大对比!
2015/12/24 PHP
php使用GD2绘制几何图形示例
2017/02/15 PHP
js有关元素内容操作小结
2011/12/20 Javascript
setInterval()和setTimeout()的用法和区别示例介绍
2013/11/17 Javascript
关于Javascript作用域链的八点总结
2013/12/06 Javascript
JavaScript原型链示例分享
2014/01/26 Javascript
EasyUI中实现form表单提交的示例分享
2015/03/01 Javascript
详解Node.js如何开发命令行工具
2016/08/14 Javascript
JS实现表单验证功能(验证手机号是否存在,验证码倒计时)
2016/10/11 Javascript
js获取当前周、上一周、下一周日期
2017/03/19 Javascript
Angular.JS通过指令操作DOM的方法
2017/05/10 Javascript
elemetUi 组件--el-upload实现上传Excel文件的实例
2017/10/27 Javascript
不使用 JS 匿名函数理由
2017/11/17 Javascript
完美解决手机网页中输入框被输入法遮挡的问题
2017/12/19 Javascript
angular6.0使用教程之父组件通过url传递id给子组件的方法
2018/06/30 Javascript
Vue组件中的data必须是一个function的原因浅析
2018/09/03 Javascript
vue实现弹框遮罩点击其他区域弹框关闭及v-if与v-show的区别介绍
2018/09/29 Javascript
谈谈为什么你的 JavaScript 代码如此冗长
2019/01/30 Javascript
vue实现百度下拉列表交互操作示例
2019/03/12 Javascript
解决cordova+vue 项目打包成APK应用遇到的问题
2019/05/10 Javascript
vue动态子组件的两种实现方式
2019/09/01 Javascript
[40:10]2015国际邀请赛全明星表演赛
2015/08/07 DOTA
[02:12]2015国际邀请赛 SHOWOPEN
2015/08/05 DOTA
Python将图片批量从png格式转换至WebP格式
2020/08/22 Python
详谈Python中列表list,元祖tuple和numpy中的array区别
2018/04/18 Python
Tensorflow之Saver的用法详解
2018/04/23 Python
浅谈Python3 numpy.ptp()最大值与最小值的差
2019/08/24 Python
python中wheel的用法整理
2020/06/15 Python
python 如何调用远程接口
2020/09/11 Python
Laura Geller官网:美国彩妆品牌
2018/12/29 全球购物
西班牙品牌鞋子、服装和配饰在线商店:Esdemarca
2021/02/17 全球购物
药品质量检测应届生求职信
2013/11/14 职场文书
校园之声广播稿
2014/01/31 职场文书
婚假请假条怎么写
2014/04/10 职场文书
财务工作检讨书
2014/10/29 职场文书
西双版纳导游词
2015/02/03 职场文书