微信小程序Skyline模式下瀑布长列表优化成虚拟列表,解决内存问题

微信小程序长列表,渲染的越多就会导致内存吃的越多。特别是长列表的图片组件和广告组件。

为了解决内存问题,所以看了很多人的资料,都不太符合通用的解决方式,很多需要固定子组件高度,但是瀑布流是无法固定的,所以需要找更好的方式。好在有一篇可以借鉴的文章在其基础上做了修改,解决了内存问题!

借鉴了以下文章的解决方式,由于借鉴章依旧存在内存泄漏问题,所以本文章改进后不再内存泄漏

借鉴文链接:解决小程序渲染复杂长列表,内存不足问题 - 掘金 (juejin.cn)

 进入下面小程序可以体验效果

 

 代码效果图

 老规矩,直接上代码,各位直接引用!

一、定义骨架组件

WXML:

<view class="list-item" id="list-item-{{skeletonId}}" style="min-height: {{height}}px;">
    <block wx:if="{{showSlot}}">
        <view style="height: 1px; z-index: 1;">{{parentIndex}},{{index}}</view>
        <image style="width: 100%;height: 100%;" mode="aspectFill" src="https://img-blog.csdnimg.cn/direct/25e4d10c5187409d9190a2f47297503e.jpeg"></image>
    </block>
</view>
<!-- 广告,不用可以直接去掉 -->
<block wx:if="{{(index+1)%12==0}}">
    <view class="adbk" style="min-height: {{(shkey==='list'||shkey==='tx')?'330px':'315px'}};background:#ffff">
        <block wx:if="{{showSlot}}">
            <ad-custom 
            class="girdAd" 
            unit-id="adunit-xxxxx"></ad-custom>
        </block>
    </view>
</block>

JS: 

// components/skeleton.js
let app = getApp() 
Component({
  lifetimes:{
    created(){
        //设置一个走setData的数据池
        this.extData = {
          listItemContainer: null,
        }
    },
    attached(){
        
    },
    detached() {
      try {
        this.extData.listItemContainer.disconnect()
      } catch (error) {
  
      }
      this.extData = null
    },
  
    ready() {
      this.setData({
        skeletonId: this.randomString(8), //设置唯一标识
        color:this.randomColor()
      })
      wx.nextTick(() => {
        // 修改了监听是否显示内容的方法,改为前后showNum屏高度渲染
        // 监听进入屏幕的范围relativeToViewport({top: xxx, bottom: xxx})
        let { windowHeight = 667 } = wx.getSystemInfoSync() //请自行优化这个取值
        let showNum = 2 //超过屏幕的数量,目前这个设置是上下2屏
        try {
          this.extData.listItemContainer = this.createIntersectionObserver()
          this.extData.listItemContainer.relativeToViewport({ top: showNum * windowHeight, bottom: showNum * windowHeight })
            .observe(`#list-item-${this.data.skeletonId}`, (res) => {
              let { intersectionRatio } = res
              if (intersectionRatio === 0) {
                // console.log('【卸载】', this.data.skeletonId, '超过预定范围,从页面卸载')
                this.setData({
                  showSlot: false
                })
              } else {
                // console.log('【进入】', this.data.skeletonId, '达到预定范围,渲染进页面')
                this.setData({
                  showSlot: true,
                  height: res.boundingClientRect.height
                })
              }
            })
        } catch (error) {
          console.log(error)
        }
      })
      
    }
  },
  /**
   * 组件的属性列表
   */
  properties: {
    parentIndex:{
       type:Number,
       value:0
    },
    index:{
      type:Number,
      value:0
    }
  },
  /**
   * 组件的初始数据
   */
  data: {
    height: 0, //卡片高度,用来做外部懒加载的占位
    showSlot: true, //控制是否显示当前的slot内容
    skeletonId: '',
    color:'#7179b1',
    colorList:[
      '#7179b1',
      '#d66f33',
      '#33d665',
      '#cc33d6',
      '#7233d6',
      '#338bd6',
      '#b5d2ea',
      '#6f0c0c',
      '#d43f8b',
      '#00ccec',
      '#2e666f',
      '#ffcd18'
    ]
  },

  /**
   * 组件的方法列表
   */
  methods: {
    /**
     * 生成随机的字符串
     */
    randomString(len) {
      len = len || 32;
      var $chars = 'abcdefhijkmnprstwxyz2345678'; /****默认去掉了容易混淆的字符oOLl,9gq,Vv,Uu,I1****/
      var maxPos = $chars.length;
      var pwd = '';
      for (var i = 0; i < len; i++) {
        pwd += $chars.charAt(Math.floor(Math.random() * maxPos));
      }
      return pwd;
    },
    randomColor(){
        let num = Math.ceil(Math.random()*10);
        return this.data.colorList[num];
    }
  }
})

WXSS:

.girdAd{
  border-radius: 10px;
  z-index: 11;
}
.adbk{
  background: #636363;
  border: 1px solid #f3f3f3;
  border-radius: 10px;
  margin-top: 10px;
}

.adloading{
   line-height: 300px;
   color: rgb(255, 255, 255);
   text-align: center;
   position: absolute;
   right: 23%;
}

 二、业务代码使用骨架组件

业务代码中,就是数组的数据需要频繁的使用setData这个接口,所以需要避免频繁操作。

将list 数据改成二位数组。

json需要引入:    "skeleton":"/components/skeleton/skeleton"

WXML:

<scroll-view 
   style="height: 100vh;"
  type="custom"
  scroll-y="{{true}}" 
  lower-threshold="{{100}}"
  scroll-top="0"
  scroll-with-animation="{{true}}" 
  bindscrolltolower="loadmore">
  <grid-view type="masonry" cross-axis-count="{{2}}" cross-axis-gap="{{10}}" main-axis-gap="{{10}}" padding="{{[5,5,0,5]}}">
    <block wx:for-item="parentItem" wx:for-index="parentIndex" wx:for="{{list}}" wx:key="{{parentIndex}}">
      <!-- 这个view仅作为间隔区分展示用,并不是必须的 -->
      <block wx:if="{{parentIndex!=0}}"
        wx:for="{{parentItem}}" 
        wx:key="{{index}}" >
        <!-- 使用 -->
        <skeleton parentIndex="{{parentIndex}}" index="{{index}}"></skeleton>
      </block>
    </block>
  </grid-view>
</scroll-view>

JS:


Component({
  lifetimes:{
     created(){
        this.loadmore()
     }
  },
  data: {
    list: [[{}]]
  },
  methods: {
    loadmore: function() {
      //过长的list需要做二维数组,因为setData一次只能设置1024kb的数据量,如果过大的时候,就会报错
      //二维数组每次只设置其中一维,所以没有这个问题
      let nowList = `list[${this.data.list.length}]`
      let demoList = this.getList(100)
      this.setData({
        [nowList]: demoList
      })
    },
    /**
     * 每次吸入num条数据
     */
    getList(num) {
      let list = []
      for (let i = 0; i < num; i++) {
        list.push({
          height: this.getRadomHeight()
        })
      }
      return list    
    },
    /**
     * 生成随机(100, 400)高度
     */
    getRadomHeight() {
      return parseInt(Math.random()*100 + 300)
    }
  },
})

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/529885.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

STM32H7通用定时器计数功能的使用

目录 概述 1 STM32定时器介绍 1.1 认识通用定时器 1.2 通用定时器的特征 1.3 递增计数模式 1.4 时钟选择 2 STM32Cube配置定时器时钟 2.1 配置定时器参数 2.2 配置定时器时钟 3 STM32H7定时器使用 3.1 认识定时器的数据结构 3.2 计数功能实现 4 测试案例 4.1 代码…

三极管结构难?——秒了

前边我们已经学完了PN结&#xff0c;二极管&#xff0c;在分析了二极管后&#xff0c;我们对这些东西有了一定深度的了解&#xff0c;但是只给我们一个二极管去研究&#xff0c;这玩意好像真的没啥大用&#xff0c;其实我们追求的是用半导体材料去代替电子管的放大作用&#xf…

0.开篇:SSM+Spring Boot导学

1. 为什么要使用框架 Spring是一个轻量级Java开发框架&#xff0c;最早有Rod Johnson创建&#xff0c;目的是为了解决企业级应用开发的业务逻辑层和其他各层的耦合问题。 几乎当下所有企业级JavaEE开发都离不开SSM&#xff08;Spring SpringMVC MyBatis&#xff09;Spring B…

c/c++ |游戏后端开发之skynet

作者眼中的skynet 有一点要说明的是&#xff0c;云风至始也没有公开说skynet专门为游戏开发&#xff0c;换句话&#xff0c;skynet 引擎也可以用于web 开发 贴贴我的笔记 skynet 核心解决什么问题 愿景&#xff1a;游戏服务器能够充分利用多核优势&#xff0c;将不同的业务放在…

Visual Studio Code 终端为管理员权限

第一部 1、 Visual Studio Code 快捷方式启动选项加上管理员启动 第二步 管理员方式运行 powershell Windows 10的任务栏自带了搜索。或者开始菜单选搜索只需在搜索框中输入powershell。 在出来的搜索结果中右击Windows PowerShell&#xff0c;然后选择以管理员方式运行。 执…

Apache Doris 基于 Job Scheduler 实现秒级触发任务调度能力

作者&#xff5c;SelectDB 技术团队 在数据管理愈加精细化的需求背景下&#xff0c;定时调度在其中扮演着重要的角色。它通常被应用于以下场景&#xff1a; 定期数据更新&#xff0c;如周期性数据导入和 ETL 操作&#xff0c;减少人工干预&#xff0c;提高数据处理的效率和准…

Java基于微信小程序的校园外卖平台设计与实现,附源码

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;…

03-JAVA设计模式-代理模式详解

代理模式 什么是代理模式 Java代理模式是一种常用的设计模式&#xff0c;主要用于在不修改现有类代码的情况下&#xff0c;为该类添加一些新的功能或行为。代理模式涉及到一个代理类和一个被代理类&#xff08;也称为目标对象&#xff09;。代理类负责控制对目标对象的访问&a…

Github 2024-04-09 Python开源项目日报 Top10

根据Github Trendings的统计,今日(2024-04-09统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Python项目10Vue项目1JavaScript项目1系统设计指南 创建周期:2507 天开发语言:Python协议类型:OtherStar数量:241693 个Fork数量:42010 次…

贪心算法|860.柠檬水找零

力扣题目链接 class Solution { public:bool lemonadeChange(vector<int>& bills) {int five 0, ten 0, twenty 0;for (int bill : bills) {// 情况一if (bill 5) five;// 情况二if (bill 10) {if (five < 0) return false;ten;five--;}// 情况三if (bill …

SpringBoot快速入门笔记(6)

文章目录 Axios网络请求1、简介2、导入3、网络请求4、跨域问题5、数据渲染6、全局配置 Axios网络请求 1、简介 项目开发中&#xff0c;前端页面需要的数据往往要从服务器端获取&#xff0c;这必然涉及到和服务器的通信 Axios基于promise网络请求库&#xff0c;作用于node.js和…

Apache Incubator Answer 本地开发部署

文章目录 简介Github文档插件部署 Answer开发环境编译项目初始化项目运行项目 简介 一款适合任何团队的问答平台软件。 Apache Incubator Answer是一个开源项目&#xff0c;它是一个用于构建和部署问答系统的框架。该项目是Apache软件基金会的孵化器项目&#xff0c;提供一个…

PVE下安装配置openwrt和ikuai

开端 openwrt 和 ikuai 是比较出名的软路由系统。我最早接触软路由还是因为我的一个学长要改自己家里的网络&#xff0c;使用软路由去控制网络。我听说后便来了兴致&#xff0c;也在我家搞了一套软路由系统。现在我已经做完了&#xff0c;就想着写个文章记录一下。 软路由简介…

云数据库价格一瞥(华为云、百度智能云、腾讯云、阿里云)

最近&#xff0c;大家似乎和价格“磕”上了。本文仅考虑主流产品&#xff08; RDS MySQL、Redis &#xff09;的部分主流规格&#xff0c;对各家厂商的价格做一个对比&#xff0c;供参考。 TL;DR&#xff1a; 总体来看&#xff0c;各家云厂商价格趋于持平&#xff0c;部分主流商…

关于阿里云centos系统下宝塔面板部署django/中pip install mysqlclient失败问题的大总结/阿里云使用oss长期访问凭证

python版本3.12.0 问题1 解决方案 sudo vim /etc/profile export MYSQLCLIENT_CFLAGS"-I/usr/include/mysql" export MYSQLCLIENT_LDFLAGS"-L/usr/lib64/mysql" Esc退出编辑模式 &#xff1a;wq退出并且保存 问题二 说是找不到 mysql.h头文件 CentOS ‘…

【数据结构】考研真题攻克与重点知识点剖析 - 第 8 篇:排序

前言 本文基础知识部分来自于b站&#xff1a;分享笔记的好人儿的思维导图与王道考研课程&#xff0c;感谢大佬的开源精神&#xff0c;习题来自老师划的重点以及考研真题。此前我尝试了完全使用Python或是结合大语言模型对考研真题进行数据清洗与可视化分析&#xff0c;本人技术…

Python单元测试pytest捕获日志输出

使用pytest进行单元测试时&#xff0c;遇到了需要测试日志输出的情况&#xff0c;查看了文档 https://docs.pytest.org/en/latest/how-to/capture-stdout-stderr.html https://docs.pytest.org/en/latest/how-to/logging.html 然后试了一下&#xff0c;捕捉logger.info可以用…

【Qt】网络

目录 一、Udp Socket 二、Tcp Socket 三、HTTP 在进行网络编程之前&#xff0c;需要在项目中的 .pro 文件中添加 network 模块 有时添加之后要手动编译一下项目&#xff0c;使 Qt Creator 能够加载对应模块的头文件 一、Udp Socket 主要的类有两个&#xff1a;QUdpSocket …

Octopus:2B 参数语言模型即可媲美 GPT-4 的函数调用性能

近年来&#xff0c;大语言模型在 PC、智能手机和可穿戴设备的操作系统中应用逐渐成为趋势。 例如&#xff0c;MultiOn (Garg, 2024) 和 Adept AI (Luan, 2024) 等 AI 助理工具&#xff0c;以及 Rabbit R1 (Lyu, 2024) 和 Humane AI Pin (Chaudhri, 2024) 等 AI 消费产品在消费者…

Mac 装 虚拟机 vmware、centos7等,21年网络安全面经分享

链接: https://pan.baidu.com/s/1oZw1cLyl6Uo3lAD2_FqfEw?pwdzjt4 提取码: zjt4 复制这段内容后打开百度网盘手机App&#xff0c;操作更方便哦 centos8 链接: https://pan.baidu.com/s/10KWpCUa2JkwcjYlJZVogKQ?pwdn99a 提取码: n99a 复制这段内容后打开百度网盘手机App&…