首页 > 编程 > JavaScript > 正文

vue.js2.0 实现better-scroll的滚动效果实例详解

2019-11-19 13:16:30
字体:
来源:转载
供稿:网友

什么是 better-scroll

better-scroll 是一个移动端滚动的解决方案,它是基于 iscroll 的重写,它和 iscroll 的主要区别在这里 。better-scroll 也很强大,不仅可以做普通的滚动列表,还可以做轮播图、picker 等等。

<template>  <div>    <div class="goods">      <div class="menu-wrapper" ref="menuWrapper">      </div>      <div class="food-wrapper" ref="foodWrapper">      </div>    </div>  </div></template>

与1.0版本不同的是,我们使用的是ref

<script type="text/ecmascript-6">  import BScroll from "better-scroll";  export default {    data(){  return {  currentIndex:1,  goods:[]  }   }, created(){  this.classMap=['decrease','discount','special','invoice','guarantee'];  this.$http.get('/api/goods').then((response)=>{  response=response.body;  if (response.errno===ERR_OK) {   this.goods=response.data;  }        //dom结构加载结束(nextTick这个接口是计算dom相关的,要确保原生dom已经渲染了)  this.$nextTick(()=>{   this._initScroll();  });  }); }, methods:{  _initScroll(){        // 使用better-scroll实现的关键代码  this.menuScroll=new BScroll(this.$refs.menuWrapper,{click:true});  this.foodScroll=new BScroll(this.$refs.foodWrapper,{click:true});  } }  };</script>

很简单这样页面就可以滚动了,如下图

但是,这样左右两个页面并没有联动起来,需要我们再定义一个方法来计算滚动的高度,以及在计算属性中计算左侧当前索引在哪里

从而定义左侧边栏的位置

 computed:{  //用来计算左侧当前索引在哪,从而定位到左侧边栏的位置  currentIndex(){  for (let i = 0; i < this.listHeight.length; i++) {   var height1=this.listHeight[i] ;   var height2=this.listHeight[i+1];   if(!height2||(this.scrollY >= height1 && this.scrollY < height2)){   return i;   }  }  return 0;  } }, methods:{  _initScroll(){  // 使用better-scroll实现的关键代码  this.menuScroll=new BScroll(this.$refs.menuWrapper,{click:true});  this.foodScroll=new BScroll(this.$refs.foodWrapper,{   click: true,          //探针作用,实时监测滚动位置          probeType: 3  });  this.foodScroll.on('scroll',(pos)=>{   this.scrollY=Math.abs(Math.round(pos.y))  });  },  _calculateHeight(){  let foodList=this.$refs.foodWrapper.getElementsByClassName('food-list-hook');  let height=0;  this.listHeight.push(height);  for (var i = 0; i < foodList.length; i++) {   let item=foodList[i];   height+=item.clientHeight;   this.listHeight.push(height);  }  } }//dom结构加载结束(nextTick这个接口是计算dom相关的,要确保原生dom已经渲染了)         this.$nextTick(()=>{           this._initScroll();           this._calculateHeight();         });

在dom渲染后,也是需要计算高度的.

滑动右边,实现左边联动已经实现了,接下来就是,点击左边的菜单,右边的食物相应滚动到具体的位置

给左边菜单绑定一个事件:@click="selectMenu(index,$event)"

/左边的菜单项的点击事件selectMenu(index,event){//自己默认派发事件时(BScroll),_constructed默认为true.但原生的浏览器并没有这个属性 if (!event._constructed) {   return; } //运用BScroll滚动到相应位置 //运用index去找到对应的右侧位置 let foodList=this.$refs.foodWrapper.getElementsByClassName('food-list-hook'); //滚动到相应的位置 let el=foodList[index]; //设置滚动时间 this.foodScroll.scrollToElement(el,2000);}

至此,整个联动实现的,完整代码如下

<template> <div> <div class="goods">  <div class="menu-wrapper" ref="menuWrapper">  <ul>   <li v-for="(item,index) 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>  <div class="food-wrapper" ref="foodWrapper">  <ul>   <li v-for="(item,index) 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 :src="food.icon" width="57" height="57" alt="">    </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>     <div class="price">     <span class="now">¥{{food.price}}</span><span class="old" v-show="food.oldPrice">¥{{food.oldPrice}}</span>     </div>    </div>    </li>   </ul>   </li>  </ul>  </div> </div> </div></template><script type="text/ecmascript-6"> import BScroll from "better-scroll"; const ERR_OK=0; export default { props:{  seller:{  type:Object  } }, data(){  return {  goods:[],  listHeight:[],  scrollY:0  }   }, created(){  this.classMap=['decrease','discount','special','invoice','guarantee'];  this.$http.get('/api/goods').then((response)=>{  response=response.body;  if (response.errno===ERR_OK) {   this.goods=response.data;  }  //dom结构加载结束(nextTick这个接口是计算dom相关的,要确保原生dom已经渲染了)  this.$nextTick(()=>{   this._initScroll();   this._calculateHeight();  });  }); }, computed:{  //用来计算左侧当前索引在哪,从而定位到左侧边栏的位置  currentIndex(){  for (let i = 0; i < this.listHeight.length; i++) {   var height1=this.listHeight[i] ;   var height2=this.listHeight[i+1];   if(!height2||(this.scrollY >= height1 && this.scrollY < height2)){   return i;   }  }  return 0;  } }, methods:{  _initScroll(){  // 使用better-scroll实现的关键代码  this.menuScroll=new BScroll(this.$refs.menuWrapper,{click:true});  this.foodScroll=new BScroll(this.$refs.foodWrapper,{   click: true,          //探针作用,实时监测滚动位置          probeType: 3  });  this.foodScroll.on('scroll',(pos)=>{   this.scrollY=Math.abs(Math.round(pos.y))  });  },  _calculateHeight(){  let foodList=this.$refs.foodWrapper.getElementsByClassName('food-list-hook');  let height=0;  this.listHeight.push(height);  for (var i = 0; i < foodList.length; i++) {   let item=foodList[i];   height+=item.clientHeight;   this.listHeight.push(height);  }  },  //左边的菜单项的点击事件  selectMenu(index,event){  //自己默认派发事件时(BScroll),_constructed默认为true.但原生的浏览器并没有这个属性  if (!event._constructed) {   return;  }  //运用BScroll滚动到相应位置  //运用index去找到对应的右侧位置  let foodList=this.$refs.foodWrapper.getElementsByClassName('food-list-hook');  //滚动到相应的位置  let el=foodList[index];  //设置滚动时间  this.foodScroll.scrollToElement(el,2000);  } } };</script><style lang="stylus" rel="stylesheet/stylus"> @import "../../common/stylus/mixin.styl";  .goods display:flex position:absolute top:174px bottom:46px width:100% overflow:hidden .menu-wrapper  flex:0 0 80px  width: 80px  background:#f3f5f7  .menu-item  display:table  height:54px  width:56px  padding:0 12px  line-height:14px  &.current   position:relative   z-index:10   margin-top:-1px   background:#fff   font-weight:700   .text   border-none()  .icon   display:inline-block   vertical-align:top   margin-right:2px   width:12px   height:12px   background-size:12px 12px   background-repeat:no-repeat   &.decrease   bg-image('decrease_3')   &.discount   bg-image('discount_3')    &.guarantee   bg-image('guarantee_3')    &.invoice   bg-image('invoice_3')   &.special   bg-image('special_3')  .text   display:table-cell   vertical-align:middle   width:56px   border-1px(rgba(7,17,27,0.1))   font-size:12px .food-wrapper  flex:1  .title  padding-left:14px  font-size:12px  color:rgb(147,153,159)  height:26px  border-left:2px solid #d9dde1  line-height:26px  background:#f3f5f7  .food-item  display:flex  margin:18px  padding-bottom:18px  border-1px(rgba(7,17,27,0.1))  &:last-child   border-none()   margin-bottom:0  .icon   flex:0 0 57px   margin-right:10px  .content   flex:1   .name   margin:2px 0 8px 0   height:14px   line-height:14px   font-size:14px   color:rgb(7,17,27)    .desc,.extra   line-height:10px   font-size:10px   color:rgb(147,153,159)   .desc      margin-bottom:8px   line-height:12px   .extra   .count    margin-right:12px   .price   font-weight:700   line-height:24px   .now    margin-right:8px    font-size:14px    color:rgb(240,20,20)   .old    text-decoration:line-through    font-size:10px    color:rgb(147,153,159)</style>


总结

以上所述是小编给大家介绍的vue.js2.0 实现better-scroll的滚动效果实例详解,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对武林网网站的支持!

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表