IntersectionObserver实现小程序长列表优化

这篇具有很好参考价值的文章主要介绍了IntersectionObserver实现小程序长列表优化。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

IntersectionObserver实现小程序长列表优化

关于 IntersectionObserver

思路

这里以一屏数据为单位【一个分页的10条数据,最好大于视口高度】,
监听每一屏数据和视口的相交比例,即用户能不能看到它
只将可视范围的数据渲染到页面上,其余的使用空白高度占位符代替,

可视范围可扩大到当前可视范围的上下两倍到三倍,减少滚动时留白现象

实现

大多数都是监听 scroll,结合防抖函数,来控制数据的渲染

这里我们使用小程序自带api,IntersectionObserver 来实现

小程序 IntersectionObserver

通过 IntersectionObserver 来监听可视范围内的元素,当元素进入可视范围时,将对应的数据渲染到页面上。

其返回的 intersectionRatio 为相交比例,大于0 说明进入可视范围,渲染真实数据,否则,渲染高度占位符

第一步

首先需要两个数组,一个用来存放真实数据,一个用来存放高度占位符数据

将原来的 storeList,改为二维数组,以一屏为单位进行分割

// Taro

// wholePageHeight和wholeStoreList不用放在state中,页面销毁时记得释放

// 高度占位符数据
let wholePageHeight = [];
// 真实数据
let wholeStoreList = [];

state = {
    // 当前页码
    pageCurrent: 0,
    // 渲染的数据
    storeList: [],
    // 高度占位符数据
    storeListPlaceholder: [],
    // ...
}

第二步

获取界面上的节点信息

保存所有的列表数据以及页面高度数据

每次数据请求完成,将列表数据push到 wholeStoreList 中,
然后将当前这一屏的数据放到对应页面的 pageCurrentstoreList 中,
setState后, 计算这一屏的高度,然后将其存放到 wholePageHeight

// Taro

// 分页获取列表数据
getList = async () => {
    // 接口请求数据
    const { pageCurrent } = this.state;
    const records = await api.getList({
        pageCurrent
    });
    // 分页累加
    pageCurrent++

    // 保存所有的列表数据
    wholeStoreList.push(records);
    // 设置当前这一屏的数据
    storeList[pageCurrent] = records;

    this.setState({
        storeList,
        pageCurrent,
    }, () => {
        // 数据setState后,获取当前页的高度
        this.getPageHeight();
    });
}

// 计算当前页的高度
getPageHeight = () => {
    const {
        pageCurrent,
    } = this.state;
    // 返回一个 SelectorQuery 对象实例
    const query = Taro.createSelectorQuery();
    // 查询节点信息的对象
    query
        // 在当前页面下选择第一个匹配选择器 selector 的节点。返回一个 NodesRef 对象实例,可以用于获取节点信息。
        // 类似于 CSS 的选择器
        .select(`#storePage${pageCurrent}`)
        // 添加节点的布局位置的查询请求,SelectorQuery.exec 方法后,节点信息会在 callback 中返回
        .boundingClientRect()
        // 执行所有的请求。请求结果按请求次序构成数组,在callback的第一个参数中返回。
        .exec(res => {
        if (res && res[0].height) {
            /**
             *   rect.id      // 节点的ID
             *   rect.dataset // 节点的dataset
             *   rect.left    // 节点的左边界坐标
             *   rect.right   // 节点的右边界坐标
             *   rect.top     // 节点的上边界坐标
             *   rect.bottom  // 节点的下边界坐标
             *   rect.width   // 节点的宽度
             *   rect.height  // 节点的高度
             */
            // 保存当前页的高度
            wholePageHeight.push(res[0].height);
            
            // 监听当前页的节点
            this.observePage(pageCurrent);
        }
    });
}

第三步

针对每一屏都去添加监听,判断是否需要渲染真实数据,还是高度占位符

这里通过 IntersectionObserver 来监听,当元素进入可视范围时,将对应的数据渲染到页面上。

:::tip 小细节

如果只控制一屏的显示,那么当用户快速滑动上下屏时,
会出现一屏的数据还没渲染完,就已经滚动到下一屏了,导致白屏出现

所以:需要设置 relativeToViewport top 和 bottom 参数,顶部和底部的边界,进入上下三个屏幕高度就开始渲染

:::

// Taro

observePage = () => {
    const {
        storeList,
    } = this.state;

    const windowHeight = Taro.systemInfo.windowHeight;

    // WXML节点布局相交状态
    // 创建 IntersectionObserver 对象,用于推断某些节点是否可以被用户看见、有多大比例可以被用户看见。
    const observerObj = Taro.createIntersectionObserver(this)
        // 指定页面显示区域作为参照区域之一
        .relativeToViewport({
            // 设置顶部和底部的边界,进入上下三个屏幕高度就开始渲染
            top: 3 * windowHeight, 
            bottom: 3 * windowHeight
        });
    
    // 返回IntersectionObserver对象实例,用于推断某些节点是否可以被用户看见、有多大比例可以被用户看见
    observerObj.observe(`#storePage${pageIndex}`, (res) => {
        /**
         *   res.id // 目标节点 id
         *   res.dataset // 目标节点 dataset
         *   res.intersectionRatio // 相交区域占目标节点的布局区域的比例
         *   res.intersectionRect // 相交区域
         *   res.intersectionRect.left // 相交区域的左边界坐标
         *   res.intersectionRect.top // 相交区域的上边界坐标
         *   res.intersectionRect.width // 相交区域的宽度
         *   res.intersectionRect.height // 相交区域的高度
         */
        // < 0,未相交,使用高度占位符
        if (res.intersectionRatio <= 0) {
            storeList[pageIndex] = {
                height: wholePageHeight[pageIndex]
            }
            // > 0,相交,使用真实数据
        } else {
            storeList[pageIndex] = wholeStoreList[pageIndex];
        }
        this.setState({
            storeList
        });
    });
}

第四步

在页面上渲染数据,如果当前这一屏有数据,就渲染真实数据,否则渲染高度高度占位符


// Taro

// 列表渲染
renderStoreList = () => {
    const {
        storeList,
    } = this.state;
    return (
        storeList.map((storePage, index) => (
            <View className='store-page' key={index} id={'storePage' + index}>
                {
                    // 是否存在当前页的数据
                    storePage && storePage.length ?
                        <View className='store-list'>
                            {
                                storePage.map((storeItem) => (<StoreInfo item={storeItem} key={storeItem.id} />))
                            }
                        </View>
                        :
                        // 占位组件 ---
                        <PlaceWrap customStyle={{height: storePage.height + 'px'}} />
                }
            </View>
        ))
    )
};

到此,一个长列表的优化就OK了

IntersectionObserver

看了下 caniuse ,发现除了IE,兼容性也还行,那web端也可以尝试下的

IntersectionObserver实现小程序长列表优化,小程序,小程序,微信小程序,前端,性能优化文章来源地址https://www.toymoban.com/news/detail-616795.html

到了这里,关于IntersectionObserver实现小程序长列表优化的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【微信小程序】列表滚动触底更新实现

    微信小程序开发系列 在微信小程序开发中经常遇到分页列表需要滚动到底部之后进行请求数据更新,下面介绍如何进行触底更新分页展示。使用到页面上拉触底事件的处理函数 onReachBottom 。 监听用户上拉触底事件,可以在app.json的window选项中或页面配置中设置触发距离onRea

    2024年02月05日
    浏览(36)
  • 黑马微信小程序-实现本地服务九宫格并展示商品列表

    1.1准备接口 黑马接口:https://applet-base-api-t.itheima.net/categories 说明:这是获取九宫格的数据接口 1.2使用接口  说明:声明变量获取数据。  res.data数据 编写简单css 实图展示      声明query变量  并设置导航标题 标题展示      2.1准备接口 商品列表接口:https://applet-base-api-t

    2024年02月11日
    浏览(56)
  • uni-app实现点击显示隐藏列表,兼容微信小程序

    效果:    小程序打印的结果:值一直为true   如果你试过v-if不生效,又试了v-show,还是不行!!千万不要着急! 不是自己写的不对,而是uni-app和微信小程序修改值的方式不一致造成的。反正就是不承认是自己的问题。 其实解决的办法也很简单,就是要兼容两端,写出符合

    2024年02月09日
    浏览(65)
  • uniapp-微信小程序实现swiper左右滚动切换tab,上下滚动加载列表

    思路:左右滑动使用swiper,上下滑动用scroll-view,swiper改变时同时改变tab并更新列表 坑点: 1. swiper高度问题,导致滑动不到最底部和最顶部         需要手动计算,减去顶部高度和底部tabbar,并且需要同时设置padding-top和paddin-botton,否则列表显示不完整 2. 由于最开始的代码

    2024年02月04日
    浏览(59)
  • uniapp实现城市列表选择获取经纬度、附带搜索功能(移动端、微信小程序)

    所用到的技术 腾讯地图微信小程序SDK 高德地图WebServiceAPI服务 APP获取是否授权插件 uview框架(不是必须) 接下来带大家去申请 腾讯地图微信小程序SDK 微信小程序JavaScript SDK 点击下载 JavaScriptSDK v1.2 然后去申请腾讯地图的 key 先创建应用 在添加key 在应用列表中就能看到我们申

    2024年02月11日
    浏览(64)
  • uniapp微信小程序投票系统实战 (SpringBoot2+vue3.2+element plus ) -我创建的投票列表实现

    锋哥原创的uniapp微信小程序投票系统实战: uniapp微信小程序投票系统实战课程 (SpringBoot2+vue3.2+element plus ) ( 火爆连载更新中... )_哔哩哔哩_bilibili uniapp微信小程序投票系统实战课程 (SpringBoot2+vue3.2+element plus ) ( 火爆连载更新中... )共计21条视频,包括:uniapp微信小程序投票系统实

    2024年01月21日
    浏览(53)
  • 微信小程序--列表展示

    小知识: wx:for=\\\"{{list}}\\\"用来循环数组。 wx:for-item=‘变量名(随便起)’   它是指定循环数据当前的变量名,可以通过  {{变量名.属性}} 展示数组的元素。 wx:for-index=‘变量名(随便起)’,它是指向当前元素的下标名,可以在其他事件中定义自定义事件(data-xxx=\\\'{{变量名}}

    2024年02月15日
    浏览(35)
  • 微信小程序——商品列表

    主页面 引入组件 组件部分代码

    2024年02月12日
    浏览(39)
  • 微信小程序 《新闻列表》 案例

    今天带着练习一个小程序的基础练习 《新闻列表》 内容如图: 如要求: 1.主页头部的轮播图 2.中间内容上的信息案列排版。 3.上拉加载内容。 4.在信息加载完成后,给用户提示 我们看一下这个关于轮播图的相关文档。 文档地址:https://developers.weixin.qq.com/miniprogram/dev/compon

    2024年02月08日
    浏览(39)
  • 微信小程序电影列表(一)

    } .more{ float: right; } .more-text{ vertical-align: middle; margin-right: 10rpx; color: #1f4ba5; } .more-img{ width: 9rpx; height: 16rpx; vertical-align: middle; } .movies-container{ display: flex; flex-direction: row; } 编写电影界面整体样式 movies.wxss @import “movie-list/movie-list-template.wxss”; 从服务器获取数据 我们将使用豆瓣

    2024年02月09日
    浏览(44)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包