最近公司要开发小程序,其中有一个功能,需要左边的导航栏和右边的内容对应联动,其实就想饿了么外卖的选单界面,但是在小程序里实现又有点不同了。
最终效果如图
右边内容容器是可以滚动的,可以使用小程序提供的scroll-view组件,要强调的是,必须给节点设置高度
scroll-into-view就是内容栏的一个钩子,通过控制contentActive的值来控制内容栏的显示。
滚动的问题好解决,那么联动呢?我们需要的联动必须是左右相互的,即点击导航栏,内容会跟着滚动到对应的位置,滑动内容区域,导航栏也会有对应的动作,比如高亮。
小程序的组件属性中有一个scroll-into-view的属性
这其实就是一个锚点,给内容块分别不同的id,那么动态改变id值就可以让对应的内容滑到可视区了。这个属性可以满足导航栏联动内容区域的功能。
数据:
data: {
typeData: [],
contentActive: '', // 内容栏选中id
navActive: '', // 导航栏选中id
heightArr: [],
containerH: 0
}
渲染的时候就要提前把内容栏 各模块的id(加上tty是因为小程序不允许id以数字开头)绑定在对应的导航栏上,索引页绑上去,用于给选中状态标示
而内容渲染的时候页用type数据,并且id和导航栏的自定义id一致
点击导航栏时就可以通过小程序的方法拿到id和该项目的索引,并赋值
chooseType(e) {
let id = e.currentTarget.dataset.id;
let index = e.currentTarget.dataset.index;
this.setData({
contentActive: id,
navActive: index
})
// console.log(id)
}
这样通过点击导航栏,内容也会自动滚动到指定位置了,并且导航栏对应的标题高亮效果
这里有个注意点需要说一下,控制导航栏active的参数和内容栏active的参数不能是同一个,不然会冲突,主要是后面内容栏联动导航栏时的bug,所以这里分开控制。
反过来,右边联动左边就比较麻烦了,小程序没有提供反向联动的功能,只能自己实现了。
这里scroll-view提供了一个bindscroll事件
可以看到,返回的值有scrollTop,代表滚动的距离,那么就可以利用这个数据做做文章了。
思路:要想联动,就需要知道内容滚动的区域,具体是属于哪个大类的范围距离里,然后据此改变导航栏的active值。要知道滚动区域,就需要计算每个内容模块的高度,并累加。在滚动的时候监听滚动距离,与高度的累加值进行比较,得出此时正在哪个大类的区域。
渲染完成时获取模块高度,并进行数据处理,形成新的数组
当scroll-view滚动的时候,就可以获取到滚动的距离,并动态计算滚动区间,是在heightArr的哪个区间里面,并返回对应的索引
这样就实现了联动效果