小程序吸顶+锚点导航| 8月更文挑战

2,636 阅读2分钟

开发微信小程序时,经常会遇到一些特别的功能,单页面的锚点导航,目前好像没什么开放组件可以直接用到微信小程序中,今天分享一下~

1、定义导航条内容及高度

使用循环动态展示,这样可以更好的管理页面锚点吸顶后展示的效果,并定义toView和navIdx设置目的导航条位置

初始化的时候获取scrollview所有模块的高度,为锚点滚动使用,并且获取节点距离顶部的距离

wxml
    <view class="navbar-wrap">        <view class="scrollListBox {{isFixedTop?'fixed':''}}" id="navbar">            <view wx:for="{{navList}}" wx:for-index="idx" wx:key="index" bindtap='clickScroll' data-idx="{{idx}}" data-id="{{item.id}}" class="scrollListItem {{idx == navIdx ? 'onScrollNav':''}}">                {{item.name}}            </view>            <!-- 用于吸顶后占位 -->        </view>        <view class="scrollListBox" wx:if="{{isFixedTop}}"></view>    </view>js:
data: {
    navbarInitTop: 0, //导航栏初始化距顶部的距离    isFixedTop: false, //是否固定顶部    toView:"",    navIdx:0,    navList:[            {                id: "list0",                name:"简介"            },{                id: "list1",                name:"价格"            },{                id: "list2",                name:"周边"            },{                id: "list3",                name:"附近"            }     ],
},
onShow: function () {        var that = this;        let query = wx.createSelectorQuery().in(this);        let heightArr =[];        let h = 0;        query.selectAll('.scrollListItem').boundingClientRect((react)=>{            react.forEach((res)=>{                h+=res.height;                heightArr.push(h)            })            this.setData({                anchorArray:heightArr            });        }).exec();        //导航栏吸顶        if (that.data.navbarInitTop == 0) {            //获取节点距离顶部的距离            wx.createSelectorQuery().select('#navbar').boundingClientRect(function(rect) {                if (rect && rect.top > 0) {                    var navbarInitTop = parseInt(rect.top);                    that.setData({                        navbarInitTop: navbarInitTop                    });                }            }).exec();        }
},
wxss:
.navbar-wrap {    width: 100%;    line-height: 102rpx;}scroll-view {    height: 600px;}.scrollListBox{      width: 100%;    line-height: 102rpx;    background: #f6f8fc;    top: 0;    left: 0;    z-index: 100;}.navbar-wrap .scrollListBox.fixed {    position: fixed;}.scrollListItem {    font-size: 28rpx;    display: inline-block;    width: 20%;    line-height: 70rpx;    color: #1A1A1A;    text-align: center;}.onScrollNav{     color: #10AEFF;    border-bottom: 2px solid #10AEFF;}.swiperLine {    width: 30px;    height: 3px;    background-color: #10AEFF;    border-radius: 4px;    margin-left: 32rpx;}.swiper-box{ display: block; height: 100%; width: 100%;}

2、页面内容定义,锚点点击/滑动跳转后的位置

<scroll-view scroll-y    scroll-into-view="{{toView}}"    bindscroll="scrollTopFun"    style="height:100vh;background: #f6f8fc;"    scroll-with-animation="true"    >        <!-- 简介 -->        <view class="navListView" id="list0"></view>
        <!-- 价格 -->        <view class="navListView" id="list1"></view>
        <!-- 周边 -->        <view class="navListView" id="list2"></view>
        <!-- 附近 -->        <view class="navListView" id="list3"></view></scroll-view>

注:这里的每个id都要和上面定义的list里的id内容一致,使用scroll-view滑动更顺畅,感觉之前写的分页后来加了scroll-view也更顺滑,还是很好用的,之前没有get到

3、监听页面滑动,动态选中当前锚点的导航条

onPageScroll: function(e) {        var that = this;        var scrollTop = parseInt(e.scrollTop); //滚动条距离顶部高度        var isOk = scrollTop >= that.data.navbarInitTop ? true : false;        if (that.data.isFixedTop === isOk) {            return false;        }                that.setData({            isFixedTop: isSatisfy        });},

监听页面滑动事件,判断滚动条滚动的距离和元素初始与顶部的距离,并为了不会一直setData则增加死循环判断isOk 。

4、点击锚点滑动到页面导航的位置

通过获取当前view距离顶部的位置判断当前展示的内容是第几个导航条,然后导航条内容高亮展示选中

     scrollTopFun: function (e) {        let scrollTop=e.detail.scrollTop;        let scrollArr= this.data.anchorArray;        if(scrollTop>=scrollArr[scrollArr.length-1]){            return;        }else {            for(let i=0;i<scrollArr.length;i++){                if(scrollTop>=0&&scrollTop<scrollArr[0]){                    // navIdx控制筛选块高亮显示                    this.setData({                        navIdx: 0                    });                }else if(scrollTop>=scrollArr[i-1]&&scrollTop<scrollArr[i]) {                    this.setData({                        navIdx: i                    });                }            }        }    },    //点击锚点导航栏    clickScroll: function (e) {        this.setData({            toView: e.target.dataset.id,            navIdx: e.target.dataset.idx        })    },

点击锚点,就可以直接定义当前想跳转的导航内容,通过toView和navIdx直接滑动到目的内容

一共分为4个步骤,不过不是特别详细,因为我觉得看这篇文章的人都是想直接解决问题,可以试下是否可以,已经用在项目中才分享的~