设计初衷
在开发页面时,往往需要实现,点击页面的导航菜单页面滚动到相应位置,滚动页面实现菜单选项的高亮。在html开发中,我们可以用到a标签锚点实现,jq的动画相结合实现类似效果。在框架中vant UI框架也为我们实现了这一效果。
效果展示
当菜单导航滚动到页面顶部时,菜单吸顶
当点击菜单按钮时,切换到对应区域(过渡到该区域,有动画效果)
当内容区滚动到某类区域时,对应区域的菜单按钮高亮

设计思路
1、吸顶效果的实现
获取菜单导航距离页面顶部距离
wx.createSelectorQuery()页面滚动监听
滚动距离与菜单初始位置值比较
1) 距离
const query = wx.createSelectorQuery()query.select('.menu_nav').boundingClientRect(function(res) { let obj = {} if (res && res.top) { obj[item.attr] = parseInt(res.top) }}).exec()① wx.createSelectorQuery()
返回一个 SelectorQuery 对象实例。在自定义组件或包含自定义组件的页面中,应使用 this.createSelectorQuery() 来代替。
② SelectorQuery.select(string selector)
在当前页面下选择第一个匹配选择器 selector 的节点。返回一个 NodesRef 对象实例,可以用于获取节点信息。
selector 语法
selector类似于 CSS 的选择器,但仅支持下列语法。
③ NodesRef.boundingClientRect(function callback)
添加节点的布局位置的查询请求。相对于显示区域,以像素为单位。其功能类似于 DOM 的 getBoundingClientRect。返回 NodesRef 对应的 SelectorQuery。
属性类型说明idstring节点的 IDdatasetObject节点的 datasetleftnumber节点的左边界坐标rightnumber节点的右边界坐标topnumber节点的上边界坐标bottomnumber节点的下边界坐标widthnumber节点的宽度heightnumber节点的高度
④ SelectorQuery.exec(function callback)
执行所有的请求。请求结果按请求次序构成数组,在callback的第一个参数中返回。
2) 页面滚动监听
data中初始化--tabFixed=false(表示是否固定定位)
滚动条滚动距离超过了菜单初始距离时,tabFixed=true开启定位
// 监听页面滚动onPageScroll: function(e) { let hTop = parseInt(e.scrollTop) // 菜单是否需要定位到顶部 if (hTop > this.data.menu_top) { this.setData({ tabFixed: true }) } else { this.setData({ tabFixed: false }) }}onPageScroll(Object object))
监听用户滑动页面事件。
参数 Object object:
注意:请只在需要的时候才在 page 中定义此方法,不要定义空方法。以减少不必要的事件派发对渲染层-逻辑层通信的影响。 注意:请避免在 onPageScroll 中过于频繁的执行 setData 等引起逻辑层-渲染层通信的操作。尤其是每次传输大量数据,会影响通信耗时。
2、切换到对应区域
记录当前点击的菜单并高亮
获取每个区域初始距离页面顶部距离
设置当前页面滚动条滚动到的位置,设置过度时间
// 导航栏切换设置setSelectType(event) { let index = event.currentTarget.dataset.type this.setData({ tabIndex: index, }) let arr = ['panel1_top', 'panel2_top', 'panel3_top', 'panel4_top'] let _this = this wx.pageScrollTo({ scrollTop: _this.data[arr[index]], duration: 500 })},wx.pageScrollTo(Object object)
将页面滚动到目标位置,支持选择器和滚动距离两种方式定位
3) 滚动到某类区域时,对应区域的菜单按钮高亮
获取初始时区域距离顶端距离
let arr = [ { name: '.menu-nav', attr: 'menu_top', addNum: 0 }, { name: '.panel1', attr: 'panel1_top', addNum: 0 }, { name: '.panel2', attr: 'panel2_top', addNum: 0 }, { name: '.panel3', attr: 'panel3_top', addNum: 0 }, { name: '.panel4', attr: 'panel4_top', addNum: 0 },]arr.forEach((item, i) => { wx.createSelectorQuery().select(item.name).boundingClientRect(function(res) { let obj = {} if (res && res.top) { obj[item.attr] = parseInt(res.top) if (item.addNum) { obj[item.attr] += item.addNum } that.setData({ ...obj }) }

