VUE饿了么学习笔记(6)goods界面滚动和点击联动的实现
使用插件Bscroll,在依赖文件package.json中添加版本,在install,run之后使用1)import BScroll from2)BScroll实例化的时候要接收一个DOM,此处将实例化并获取DOM的过程封装成方法,获取DOM<div class="menu-wrapper" ref="menuWrapper">
使用插件Bscroll,在依赖文件package.json中添加版本,在install,run之后使用
1)import BScroll from
2)BScroll实例化的时候要接收一个DOM,此处将实例化并获取DOM的过程封装成方法,获取DOM
<div class="menu-wrapper" ref="menuWrapper">
<div class="foods-wrapper" ref="foodsWrapper">
methods: {
_initScroll() {
//v-el(this.$els.foodWrapper)获取DOM对象,json对象
this.menuScroll = new BScroll(this.$refs.menuWrapper, {
click: true //阻止默认,允许点击
});
this.foodsScroll = new BScroll(this.$refs.foodsWrapper, {
click: true,
probeType: 3 //BScroll滚动时,能实时告诉我们滚动的位置,类似探针的效果
});
//foodsScroll监听事件,在scroll滚动时能见位置实时暴露出来
this.foodsScroll.on('scroll', (pos) => {
this.scrollY = Math.abs(Math.round(pos.y)); //取正值
});
}
在created中添加初始化,在this.$nextTick(() => {初始化})
created() {
this.classMap = ['decrease', 'discount', 'special', 'invoice', 'guarantee'];
//请求的ajex地址,成功的回调,拿到一个response
this.$http.get('/api/goods').then((response) => {
//response是一个属性,将其转化为json对象
response = response.body;
//console.log(response);
if (response.errno === ERR_OK) {
// 数据在data字段中,将goods对象传给header组件,通过:goods
this.goods = response.data;
// console.log(this.goods);
//初始化betterScroll的时候,DOM的更新时异步的,所以我们在这虽然改变了数据,但是DOM并没有变化,计算不到正确的高度
this.$nextTick(() => {
//调用scroll函数,实现滚动
this._initScroll();
//拿到数据以后计算高度
this._calculateHeight();
});
}
});
}
左右两侧都可以产生的滚动效果
3)滚动右侧时左侧相应滚动,计算右侧不同区间高度的一个数组,然后对比当前滑动的坐标落在哪个区间,并取到这个区间的索引值,就可以知道左侧导航栏要高亮的索引值了,利用vue的class绑定令其高亮
在data中定义数组用来存储不同区间的高度
data() {
return {
goods: [],
listHeight: [] //存储区块的高度
};
}
为了获取高度,给food-list定义一个class--food-list-hook,不用来编写css,专门用来获取DOM元素,没有实际的效果,只是用来被js选择的
<div class="foods-wrapper" ref="foodsWrapper">
<ul>
<li v-for="item in goods" :key="item.id" class="food-list food-list-hook">
foodList拿到了每个li,每个li是包括包括标题在内的每一类food的高度,不是单独的一种good,将_calculateHeight放在nextTick中初始化_initScroll的后面,保证其能正确计算到高度
_calculateHeight() {
//food-list-hook类的添加知识为了能拿到food列表,例如,拿到的是多个类似整个粥品的区块
let foodList = this.$refs.foodsWrapper.getElementsByClassName('food-list-hook');
let height = 0;
this.listHeight.push(height); //listHeight是一个递增的区间数组,是每个专区高度的累加
for (let i = 0; i < foodList.length; i++) {
let item = foodList[i];
height += item.clientHeight;
this.listHeight.push(height);
}
}
在data中定义一个scrollY对象,用来跟踪滚动的高度 scrollY:0;在初始化betterScroll时,为右侧添加probeType,可以检测到右侧实时滚动的位置,监听scroll,将其实时滚动的位置暴露出来
this.foodsScroll = new BScroll(this.$refs.foodsWrapper, {
click: true,
probeType: 3 //BScroll滚动时,能实时告诉我们滚动的位置,类似探针的效果
});
//foodsScroll监听事件,在scroll滚动时能见位置实时暴露出来
this.foodsScroll.on('scroll', (pos) => {
this.scrollY = Math.abs(Math.round(pos.y)); //本身是个负值,取正值
})
4)拿到滚动的高度和内容区的固定高度之后, 查看scrollY落在哪个区间,并返回那个区间的索引(!height2是测试最后一个区间的)其中,>= 向下的是一个闭区间,这样第一个就会高亮了
computed: {
currentIndex() { //currentIndex对应菜单栏的下标
for (let i = 0; i < this.listHeight.length; i++) { //不要忘了加this引用
let height1 = this.listHeight[i];
let height2 = this.listHeight[i + 1];
//获得了一个区间的上下范围,判断scrollY落到这个区间,!height2是判断最后一个区间
//避免i溢出,>= 向下的是一个闭区间,这样第一个就会高亮了
if (!height2 || (this.scrollY >= height1 && this.scrollY < height2)) {
return i; //映射到第5行menu的变化
}
}
return 0;
拿到index之后,回到左侧的menu区,当我们遍历menu的时候,如果$index等于我们计算得到的currentIndex时,就为当前的li添加一个current样式
<!-- 如果index等于currentIndex,就为这个li添加一个current类,改变左侧导航栏的背景颜色-->
<li v-for="(item,index) in goods" :key="item.id" class="menu-item" :class="{'current': currentIndex === index}"
@click = "selectMenu($index, $event)"> <!-- click所传递的事件-->
&.current
position relative
margin-top -1px
background #fff
font-weight 700
z-index 10
.text
border-none()
5)点击左侧右侧滚动
在左侧菜单栏添加点击事件selectMenu, @click = "selectMenu($index, $event)",将index传进去,就可以知道点选的是哪个区域,然后利用原生DOM操作将高度滚动到相应的位置
点击左侧菜单栏的时候没有反应,因为BScroll默认阻止点击事件,所以在 _initScroll()中获取DOM对象时添加click: true,并解决PC端双点击问题,event是点击时的event
selectMenu (index, event) {
if (!event._constructed) { //浏览器直接return掉,去掉自带click事件的点击
return;
}
let foodList = this.$refs.foodsWrapper.getElementsByClassName('food-list-hook');
let ref = foodList[index]; //取到index对应的DOM
this.foodsScroll.scrollToElement(ref, 300);//滚动到DOM所在位置
//console.log(index);
}
更多推荐
所有评论(0)