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

news2024/11/25 10:55:06

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

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

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

借鉴文链接:解决小程序渲染复杂长列表,内存不足问题 - 掘金 (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)
    }
  },
})

 

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SpringBoot常用注解及其使用示例

Spring Boot是一个用于快速构建Java应用程序的框架&#xff0c;它简化了Spring应用程序的创建和部署过程。 Spring Boot提供了很多注解&#xff0c;用于简化开发过程&#xff0c;提高开发效率。本文将介绍几个Spring Boot常用注解的使用案例&#xff0c;包括Controller、Reques…

【Xilinx】FPGA中的HPI/O和HRI/O的说明 (hpio hrio)

Xilinx 一些系列FPGA IO Bank分为HP Bank和HR Bank&#xff0c;HP IO接口电压范围为1.2V~1.8V&#xff0c;可以实现高性能&#xff0c;HR IO接口电压范围为1.2V~3.3V。当HR Bank与2.5V或者3.3V外设互联时&#xff0c;需要考虑接口电平的兼容性。 含义 电平 HP接口为高速接口 …

实验模拟gfs 五大逻辑卷

目录 一 实验环境 二 4台服务端准备工作 1&#xff0c;66,77,88,99 四台机器加4块磁盘 2&#xff0c; scan 刷新磁盘供电接口 并查看 3&#xff0c;改主机名&#xff0c;方便后续操作 4&#xff0c;为加快访问速度 写hosts文件 做映射&#xff08;55客户机也写&…

13-pyspark的共享变量用法总结

目录 前言广播变量广播变量的作用 广播变量的使用方式 累加器累加器的作用累加器的优缺点累加器的使用方式 PySpark实战笔记系列第四篇 10-用PySpark建立第一个Spark RDD(PySpark实战笔记系列第一篇)11-pyspark的RDD的变换与动作算子总结(PySpark实战笔记系列第二篇))12-pysp…

【AcWing】蓝桥杯集训每日一题Day16|哈希|FloodFill算法|字典序最小|映射|1402.星空之夜(C++)

1402.星空之夜 1402. 星空之夜 - AcWing题库难度&#xff1a;中等时/空限制&#xff1a;1s / 64MB总通过数&#xff1a;3415总尝试数&#xff1a;7434来源&#xff1a;usaco training 5.1算法标签Flood Fill哈希DFSBFS 题目内容 夜空深处&#xff0c;闪亮的星星以星群的形式出…

雅特力AT32引脚复用记录

用作USB的话&#xff0c;PA9不能再用作其他功能了 被复用了。这个关联信号是OTG_FS_VBUS。stm32是能这么复用的。

大型央国企“信创化”与数字化转型建设思路

一、央国企信创化与数字化转型时代背景 1、信创概念普及&#xff1a; 信创&#xff0c;即“信息技术应用创新”。是我国自主信息产业聚焦的核心&#xff0c;旨在通过对IT硬件、软件等各个环节的重构&#xff0c;基于我国自有IT底层架构和标准&#xff0c;形成自有开放生态&am…

阿里云OSS使用流程

准备工作 无论怎么样&#xff0c;你需要准备一个阿里云账号&#xff0c;点击&#xff1a;注册阿里云 输入相关信息&#xff0c;然后注册成功以后&#xff0c;点击 然后注册成功了&#xff0c;实名一下阿里云账号。打开实名入口&#xff0c;选择个人实名或者企业实名。 如果你…

Xinstall:专业的App下载量统计工具,让推广效果可衡量

在移动互联网时代&#xff0c;App的下载量是衡量一个应用受欢迎程度的重要指标。然而&#xff0c;很多开发者和广告主在推广App时&#xff0c;都面临着一个共同的问题&#xff1a;如何准确统计App的下载量&#xff1f;这不仅关系到推广效果的评估&#xff0c;还直接影响到广告R…

【Linux 学习】进程优先级和命令行参数!

1. 什么是优先级? 指定进程获取某种资源&#xff08;CPU&#xff09;的先后顺序&#xff1b; Linux 中优先级数字越小&#xff0c;优先级越高&#xff1b; 1.1 优先级和权限的区别&#xff1f; 权限 &#xff1a; 能不能做 优先级&#xff1a; 已经能了&#xff0c;但是获…

Linux初学(十七)防火墙

一、防火墙简介 1.1 防火墙的类别 安全产品 杀毒&#xff1a; 针对病毒&#xff0c;特征篡改系统中的文件杀毒软件针对处理病毒程序防火墙&#xff1a; 针对木马&#xff0c;特征系统窃取防火墙针对处理木马 防火墙分为两种 硬件防火墙软件防火墙 硬件防火墙 各个网络安全…

模型量化——NVIDIA——方案选择(PTQ、 partialPTQ、 QAT)

PTQ、 partialPTQ、 QAT 选择流程 PTQ、 partialPTQ、 QAT 咨询NVIDIA 官方后&#xff0c;他们的校正过程一致&#xff0c;支持的量化算子本质是一样的&#xff0c;那么如果你的算子不是如下几类&#xff0c;那么需要自己编写算子。参考TensorRT/tools/pytorch-quantization/py…

淘宝销量API商品详情页原数据APP接口测试㊣

淘宝/天猫获得淘宝app商品详情原数据 API 返回值说明 item_get_app-获得淘宝app商品详情原数据 公共参数 名称类型必须描述keyString是调用key&#xff08;必须以GET方式拼接在URL中&#xff09;secretString是调用密钥api_nameString是API接口名称&#xff08;包括在请求地…

码蹄集部分题目(第五弹;OJ赛2024年第10期)

&#x1f40b;&#x1f40b;&#x1f40b;竹鼠通讯&#xff08;钻石&#xff1b;分治思想&#xff1b;模板题&#xff1a;就算几何平面点对问题&#xff09; 时间限制&#xff1a;3秒 占用内存&#xff1a;128M &#x1f41f;题目描述 在真空中&#xff0c;一块无限平坦光滑…

基于SSM+Jsp+Mysql的高校毕业设计管理系统

开发语言&#xff1a;Java框架&#xff1a;ssm技术&#xff1a;JSPJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包…

【三十六】【算法分析与设计】综合练习(3),39. 组合总和,784. 字母大小写全排列,526. 优美的排列

目录 39. 组合总和 对每一个位置进行枚举 枚举每一个数出现的次数 784. 字母大小写全排列 526. 优美的排列 结尾 39. 组合总和 给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target &#xff0c;找出 candidates 中可以使数字和为目标数 target 的 所有 不…

【信贷后台管理之(五)】

文章目录 目录结构一、面包屑组件封装二、退出登录接口联调三、申请列表的菜单路由3.1 路由创建&#xff0c;表格编写3.2 列表接口调用3.3 出生日期转变3.4 申请状态3.5 申请列表的操作3.5.1 编辑删除提交操作3.5.2 禁用状态3.5.3 操作接口3.5.4 搜索查询3.5.5 申请列表分页功能…

Leetcode面试经典150_Q14最长公共前缀

题目&#xff1a; 编写一个函数来查找字符串数组中的最长公共前缀。如果不存在公共前缀&#xff0c;返回空字符串 ""。 思路A&#xff1a;横向/纵向扫描 Python&#xff1a; class Solution:def longestCommonPrefix(self, strs: List[str]) -> str:s "…

NPDP含金量高吗?什么人适合学习NPDP?

省流版&#xff1a;NPDP含金量挺高的&#xff0c;做产品的建议去学习下~ 一、什么是NPDP&#xff1f; NPDP 是产品经理国际资格认证&#xff0c;美国产品开发与管理协会&#xff08;PDMA&#xff09;发起的&#xff0c;是目前国际公认的唯一的新产品开发专业认证&#xff0c;…

LeetCode-279. 完全平方数【广度优先搜索 数学 动态规划】

LeetCode-279. 完全平方数【广度优先搜索 数学 动态规划】 题目描述&#xff1a;解题思路一&#xff1a;Python 动态规划五部曲&#xff08;完全平方数就是物品&#xff08;可以无限件使用&#xff09;&#xff0c;凑个正整数n就是背包&#xff0c;问凑满这个背包最少有多少物品…