vue.js2.0 实现better-scroll的滚动效果实例详解
程序员文章站
2022-06-30 09:51:10
什么是 better-scroll
better-scroll 是一个移动端滚动的解决方案,它是基于 iscroll 的重写,它和 iscroll 的主要区别在 。bet...
什么是 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的滚动效果实例详解,希望对大家有所帮助