小程序实现tab切换与内容联动

2,023 阅读1分钟

百度小程序实现上下联动。实现上面滚动,下面内容滑动到对应区域,下面内容滑动,tab进行切换。

image.png

首先切换实现下方内容滚动,滚动内容需要获取每一部分距离顶部距离。

通过swan.createSelectorQuery获取选取元素的相关信息。

//获取每块内容距离盒子顶部距离
setScrollList() {
        return new Promise((resolve, reject) => {
            swan.createSelectorQuery()
                .selectAll('.catagory-item')
                .fields({
                    id: false,
                    dataset: false,
                    rect: true,
                    size: true,
                    scrollOffset: true,
                    properties: ['scrollX', 'scrollY'],
                }, res => {
                    resolve(res)
                }).exec();
        })

    },

获取顶部导航栏的高度

 /**
     * 获取tab高度
     */
    setTabHeight() {
        return new Promise((resolve, reject) => {
            swan.createSelectorQuery()
                .select('.tab-swap').boundingClientRect(res => {
                    resolve(res)
                }).exec()
        })
    },

为了最后一个块元素可以滑动到顶部,还需要计算撑起高度进行高度填充。需要填充的高度就是父盒子高度-最后一块内容的高度

 /**
     * 获取盒子高度
     * @param {*} e
     */
    setContainerHeight() {
        return new Promise((resolve, reject) => {
            swan.createSelectorQuery()
                .select('.container').boundingClientRect(res => {
                    resolve(res)
                }).exec()
        })
    },

因为获取的元素信息都是异步返回,使用async await 的同步写法。保证元素顺序返回

    //滚动数据处理
    async setScrollData() {
        const tabHeightInfo = await this.setTabHeight();
        const seizeHeightInfo = await this.setContainerHeight();
        const scrollTopList = await this.setScrollList();
        this.setData({
            seizeHeight: seizeHeightInfo.height,
            tabHeight: tabHeightInfo.height
        })
        this.setData({
            topList: scrollTopList.map(item => {
                return parseInt(item.top - this.data.tabHeight, 10)
            }),
            heightList: scrollTopList.map(item => {
                return item.height
            })
        })
        //计算需要添加高度 
        this.setData({
            seizeHeight: this.data.seizeHeight - this.data.heightList[this.data.heightList.length - 1]
        })
        //设置上个页面传递的id所需滚动高度
        if (this.data.categoryId) {
            this.setData({
                scrollTop: this.data.topList[this.data.activeIndex]
            })
        }

    },

调用scroll-view的滚动事件

 /**
     * scroll-view 滚动
     * @param {*} e
     */
    onScroll(e) {
        let scrollY = e.detail.scrollTop
        //根据滚动高度改变分类导航
        let index = this.data.topList.findIndex((item, index) => {
            if (index === this.data.topList.length - 1) {
                return scrollY >= item
            } else {
                return scrollY >= item && scrollY < this.data.topList[index + 1]
            }
        })
        this.setData({
            activeTab: index
        })
    },

完成以后进行调用,调用的时候嗯~为了确保内容正确返回,可以使用setTimeout延迟一下下

实现tab切换,内容滚动

/**
     * 切换导航
     * @param {*} e
     */
    changeCategory(e) {
        this.setData({
            activeTab: e.detail.name,
            scrollTop: this.data.topList[e.detail.name]   //topList就是每一块距离顶部高度
        })
    },

SWAN:静态页面

<view class="equity-container">
    <tabs class="tab-swap" active-name="{{activeTab}}" tabs-underline-color="#ff7200" tabs-inactive-text-color="#888"
        tabs-active-text-color="#ff7200" max-tab-item-amount="4" bindtabchange="changeCategory">
        <tab-item s-for="item,index in brandList" name="{{index}}" label="{{item.categoryName}}"
            data-id="{{item.categoryId}}" />
    </tabs>

    <scroll-view scroll-y class="container" scroll-into-view="{= toBrandView =}" scroll-top="{= scrollTop =}"
        bindscroll="onScroll">

        <view class="catagory-item" s-for="brandList" id="{{item.categoryId}}">
            <view class="title">{{item.categoryName}}</view>
            <view class="catagory-list">
                <view class="product-item" s-for="brand in brandList[index].list" data-id="{{brand.id}}"
                    data-type="{{brand.brandType}}" bindtap="goToProductDetailClick">
                    <view class="price">¥{{brand.salePrice}}起</view>
                    <image src="{{brand.logoUrl}}" class="product-logo"></image>
                    <view class="product-name el">{{brand.brandName}}</view>
                </view>
            </view>
        </view>
        <view style="height:{{seizeHeight}}px"></view>