微信小程序写一个可以滚动虚拟列表(瀑布流),减少dom渲染的优化,解决内存问题。

为什么要写这个?

因为在写小程序的时候首页功能比较多,造成渲染的dom有很多,一直setdata跳转到其他页面或者一直滑动就会卡顿,白屏。官方文档上那个不适用于瀑布流。官方文档

理解

刚开始在写这个的时候,就在想微信小程序的开发有虚拟dom这个概念吗,查看文档,自己实践,才大致理解一点,总结出来就是微信小程序其实并没有直接使用虚拟DOM这个概念,但提供了类似的操作DOM的方法,并且也可以根据自己的需求探索实现类似虚拟DOM的功能,所以就开始自己准备。
其实我是看了俩篇博文然后经过改造成自己的数据,然后进行理解,最后融汇贯通。我会一步一步按照自己的理解进行再代码中注释,直接复制就可以用。
第一篇
第二篇有代码片段
已附代码(如果没贴相关的代码就代表不需要写)
components->virtualItem->virtualItem.wxml

<view id="{{virtualId}}">
  <block wx:if="{{isShow}}">
    <slot></slot>
  </block>
  <view wx:else style="height: {{ height }}px"></view>
</view>

components->virtualItem->virtualItem.js

// components/virtualItem/virtualItem.js
Component({
  properties: {
    // 当前虚拟子模块唯一ID
    virtualId: {
      type: String,
      value: '',
      observer() {
        this.getCurrentItemHeight()
      }
    },
    // 父级滚动容器ID,如果需要以指定容器处理
    wrapId: {
      type: String,
      value: '',
    },
    // 离可见区域的距离,单位px
    observeDistance: {
      type: Number,
      value: 1500,
    }
  },
  data: {
    height: 0,
    isShow: true,
  },
  methods: {
    getCurrentItemHeight() {
      const query = this.createSelectorQuery();
      const { virtualId } = this.data;
      query.select(`#${virtualId}`).boundingClientRect()
      query.exec((res) => {
        this.setData({
          height: res[0].height
        }, this.observePage())
      })
    },
    observePage() {
      const { virtualId, observeDistance, wrapId } = this.data
      let IntersectionObserver = wx.createIntersectionObserver(this);
      (wrapId ? IntersectionObserver.relativeTo(`#${wrapId}`) : IntersectionObserver.relativeToViewport({ top: observeDistance, bottom: observeDistance }))
      .observe(`#${virtualId}`, ({ intersectionRatio }) => {
        this.setData({
          isShow: intersectionRatio > 0,
        })
      })
    },
  }
})

page->index->index.wxml

<view>
  <scroll-view class="virtualScrollView" eventhandle scroll-y bindscrolltolower="onScrollLower">
    <block wx:for="{{ listData }}" wx:key="screenIndex" wx:for-index="screenIndex" wx:for-item="screenItem">
      <VirtualItem virtualId="virtual_{{pageIndex}}">
        <view class="fall">
          <block wx:for="{{ screenItem.columns }}" wx:key="columnIndex" wx:for-index="columnIndex" wx:for-item="column" >
            <view style="margin-top: -{{screenItem.columnOffset[columnIndex]}}px;" class="fallCol">
              <view wx:for="{{column}}" style="height: {{ item.height }}px; background-color: {{ item.color }};" wx:key="index" wx:for-item="item" wx:for-index="index">
                screen: {{ screenIndex }}, column: {{ columnIndex }}
                这里边就可以直接写你需要的数据,不需要使用css设置瀑布流,直接就是现成的
              </view>
            </view>
          </block>
        </view>
      </VirtualItem>
    </block>
  </scroll-view>
</view>
.virtualScrollView {
  height: 100vh;
}
.fall {
  position: relative;
  display: flex;
}
.fallCol {
  flex: 1;
  display: flex;
  flex-direction: column;
}
.cell {
	margin: 5px;
}
Page({
  data: {
    listQuery: {
      pageIndex: 1,
      pageSize: 10,
    }, // 列表请求参数
    listData: [], // 列表数据
    column: 2, // 列数。需要三列可以改为3
    columnsHeights: [ 0, 0], // 每列高度如果column为3的话那么这个值就是[0, 0, 0]
  },
  onLoad() {
    this.getList();
  },
  async getList() {
    let { listQuery: { pageIndex }, column, columnsHeights } = this.data;
    const columns = [];
    // 上一组的高度数据,用于计算偏移值
    const lastHeights = [...columnsHeights];
    // 获取数据 这个就是你的真实数据,调取接口然后赋值给list。当然会异步
    // 所以可以使用Promise和async/await来确保在你调取接口之后能赋值给list成功。代码已在最底下写出
    await this.getData();  // 自己的真实数据调取的接口
    const list = this.data.getdata;
    // const list = this.getListData();
    // 初始化当前屏数据
    for (let i = 0; i < column; i++ ) {
      columns.push([]);
    }
    // 遍历新数据,分配至各列
    for (let i = 0; i < list.length; i++) {
      const position = this.computePosition(columnsHeights);
      columns[position].push(list[i]);
      // 如果使用自己的真实数据报错的话就把Number(list[i].height)改为自己喜欢的数字100或者100多
      columnsHeights[position] += Number(list[i].height);
    }
    this.setData({
      [`listData[${pageIndex}]`]: {
        columns,
        columnOffset: this.computeOffset(lastHeights),
      }
    });
    this.data.listQuery.pageIndex = pageIndex + 1;
    this.data.columnsHeights = columnsHeights;
  },

  /**
   * 获取列表数据。模拟的假数据
   */
  getListData() {
    const result = [];
    for (let i = 0; i < this.data.listQuery.pageSize; i++) {
      const height = Math.floor(Math.random() * 300);
      const item = {
        height: height < 150 ? height + 150 : height,
        color: this.randomRgbColor(),
      };
      result.push(item);
    }
    return result;
  },

  /**
   * 随机生成RGB颜色
   */
  randomRgbColor() {
    var r = Math.floor(Math.random() * 256); //随机生成256以内r值
    var g = Math.floor(Math.random() * 256); //随机生成256以内g值
    var b = Math.floor(Math.random() * 256); //随机生成256以内b值
    return `rgb(${r},${g},${b})`; //返回rgb(r,g,b)格式颜色
  },

  /**
   * 获取最小高度列下标
   */
  computePosition(heights) {
    const min = Math.min(...heights);
    return heights.findIndex((item) => item === min);
  },

  /**
   * 计算偏移量
   */
  computeOffset(heights) {
    const max = Math.max(...heights);
    return heights.map((item) => max - item);
  },

  onScrollLower() {
  // 用自己的调取接口拿到的total的总数和pageindex做判断大于总数就不掉用接口了
    this.getList();
  }
  // 封装起来的Promise
  	httpGet(url, params) {
		return new Promise((resolve, reject) => {
			http.Get(url, params, function (res) {
				if (res.status == 0) {
					resolve(res.data);
				} else {
					reject(new Error('请求失败'));
				}
			});
		});
	},
})

有好多人还有更好的思路,有的可以评论大家一起探讨。微信小程序的代码片段。有真实数据的。
代码片段打开报错的话把该换的数据换了就可以了。

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

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

相关文章

【一步一步了解Java系列】:对这个系列的总结以及对缺漏内部类知识的补充

看到这句话的时候证明&#xff1a;此刻你我都在努力 加油陌生人 br />个人主页&#xff1a;Gu Gu Study专栏&#xff1a;一步一步了解Java 喜欢的一句话&#xff1a; 常常会回顾努力的自己&#xff0c;所以要为自己的努力留下足迹 喜欢的话可以点个赞谢谢了。 作者&#xf…

大模型微调新范式:当LoRA遇见MoE

©PaperWeekly 原创 作者 | 陈思硕 单位 | 北京大学 研究方向 | 自然语言处理 图片 当 LoRA 遇见 MoE&#xff0c;会擦出怎样的火花&#xff1f; 图片 ▲ 左侧&#xff1a;原始版本的 LoRA&#xff0c;权重是稠密的&#xff0c;每个样本都会激活所有参数&#xff1b;右…

第二节:如何使用thymeleaf渲染html(自学Spring boot 3.x的第一天)

大家好&#xff0c;我是网创有方&#xff0c;今天来学习如何使用thymeleaf渲染html。该模板运用不广泛&#xff0c;所以本节内容了解既可。 第一步&#xff1a;创建html文件。 在模板templates目录下创建一个html文件。 编写代码如下&#xff1a; <!DOCTYPE html> <…

Sentinel如何使用BlockExceptionHandler实现限流/降级错误页面显示

1、修改配置项&#xff0c;打开对Spring MVC端点的保护 spring.cloud.sentinel.filter.enabledtrue 2、编写 BlockExceptionHandler的实现类 MyUrlBlockHandler.java package com.codex.terry.sentinel.urlblockhandler;/*** 文件名称: MyUrlBlockHandler.java* 编写人: yh…

tf1问题记录

在复现一个开源项目https://github.com/macanv/BERT-BiLSTM-CRF-NER。有一个疑似TensorFlow-gpu、cudnn、cuda之间版本不兼容的问题。问题详情如下&#xff1a; 在base中输入nvidia-smi显示无此命令&#xff1a; 输入nvitop可正常显示&#xff1a; 输入nvcc -V显示为&#x…

机器学习——强化学习状态值函数V和动作值函数Q的个人思考

最近在回顾《西瓜书》的理论知识&#xff0c;回顾到最后一章——“强化学习”时对于值函数部分有些懵了&#xff0c;所以重新在网上查了一下&#xff0c;发现之前理解的&#xff0c;包括网上的大多数对于值函数的描述都过于学术化、公式化&#xff0c;不太能直观的理解值函数以…

SeeSR: Towards Semantics-Aware Real-World Image Super-Resolution

CVPR2024 香港理工大学&OPPO&bytedancehttps://github.com/cswry/SeeSR?tabreadme-ov-file#-licensehttps://arxiv.org/pdf/2311.16518#page5.80 问题引入 因为有些LR退化情况比较严重&#xff0c;所以超分之后的结果会出现语义的不一致的情况&#xff0c;所以本文训…

AI影像测量:开启测量仪器的智能之眼

在基于机器视觉的影像测量中&#xff0c;一些复杂特征传统测量需要人工手动选点测量&#xff0c;不仅易受到人为因素的干扰&#xff0c;而且极大的降低测量效率&#xff0c;提高了人力成本和生产成本。AI影像测量技术运用先进的机器视觉和深度学习算法&#xff0c;可快速、准确…

工程技术类SCI,低分快刊首选期刊,无版面费!

1、期刊概况 【期刊简介】IF&#xff1a;1.0-2.0&#xff0c;JCR2区&#xff0c;中科院4区&#xff1b; 【检索情况】SCIE在检 【版面类型】正刊&#xff0c;仅少量版面&#xff1b; 【出刊频率】年刊 2、征稿范围 本刊主要是发表有关能源转型和可再生能源需求相关的研究文…

如何用程序批量下载小红书的图片?

如何使用MediaCrawler快速下载图片 作为一名图像算法工程师&#xff0c;怎么能没有图片资源呢&#xff1f;今天&#xff0c;我要介绍一个能快速下载图片的方法&#xff0c;仅供学习使用&#xff0c;请勿用于其他用途。 下载项目 首先&#xff0c;从GitHub下载项目&#xff1…

Zabbix 排坑版 Centos7

systemctl stop firewalld;systemctl disable firewalld;setenforce 0sed -i s/SELINUXenforcing/SELINUXdisabled/ /etc/selinux/configzabbix源地址,可以自己选版本&#xff0c;安装都大差不差 rpm -Uvh https://repo.zabbix.com/zabbix/5.0/rhel/7/x86_64/zabbix-release-5…

Codeforces Round 955 (Div. 2) A~E

A.Soccer&#xff08;思维&#xff09; 题意&#xff1a; 迪马喜欢看足球比赛。在这样一场比赛中&#xff0c;记分牌上的比分表示为 x x x: y y y&#xff0c;其中 x x x是第一队的进球数&#xff0c; y y y是第二队的进球数。在任何时候&#xff0c;只有一支球队可以进球&am…

超声波清洗机怎么选?极力推荐四款口碑大牌超声波清洗机

相信大家都知道超声波清洗机&#xff0c;每次眼镜脏的时候&#xff0c;去眼镜店里让老板帮忙清洗&#xff0c;她们用的就是超声波清洗机&#xff0c;通过超声波的原理深入物品深处清洁&#xff0c;清洁效果非常好。相对手洗的方式&#xff0c;超声波清洗机能够保护镜片在清洗过…

jq实现拖动滑块实现人机校验——基础积累

最近在写后台管理系统&#xff0c;同事遇到一个需求关于滑动验证的。之前的样式是&#xff1a; 现在只要底部的滑动验证&#xff0c;图片不要了&#xff0c;而且要滑动到右边才算是验证通过。 就是如下所示的最简单的验证方式&#xff1a; 由于同事现有的项目是mvc的&#…

昇思25天学习打卡营第1天|yulang

今天主要了解了深度学习框架之昇思MindSpore的初学入门&#xff0c;没想到 ai学习入门如此简单&#xff0c;不愧是华为大手笔&#xff0c;提供的学习环境配置如此之高。这个平台有点类似百度飞桨&#xff0c;大大降低了AI开发门槛&#xff0c;使用户能够快速实现想要的模型&…

Dinky 让Flink作业纵享丝滑

1.Dinky是什么&#xff1f; Dinky 是一个开箱即用的一站式实时计算平台&#xff0c;以 Apache Flink 为基础&#xff0c;连接 OLAP 和数据湖等众多框架,致力于流批一体和湖仓一体的建设与实践。Dinky 让Flink作业纵享丝滑&#xff0c;为 Apache Flink 深度定制的新一代实时计算…

【Python机器学习】模型评估与改进——留一法交叉验证

留一法也是一种常见的交叉验证方法。 我们可以将留一法交叉验证看作是每折只包含单个样本的k折交叉验证。对于每次划分&#xff0c;选择单个数据点作为测试集。这种方法可能非常耗时&#xff0c;特征是对于大型数据&#xff0c;但是小型数据集上有时可以给出更好的估计结果&am…

生产环境部署Nginx服务器双机热备部署-keepalived(多种模式教程)

前言&#xff1a;今天演示下生产环境keepalived的部署方式&#xff0c;安装模式有很多&#xff0c;比如说主备模型和双主模型&#xff0c;主备分&#xff1a;抢占模式 和 非抢占模式。这里我会一一展开说具体怎么配置一、双节点均部署Nginx&#xff1a; 第一步&#xff1a;上传…

MSYS2教程(windows环境下使用linux工具)

MSYS2教程(windows环境下使用linux工具) 1.msys2简介 MSYS2&#xff08;Minimal SYStem 2&#xff09;是一个集成了大量的GNU工具链、工具和库的开源软件包集合。它提供了一个类似于Linux的shell环境&#xff0c;可以在Windows系统中编译和运行许多Linux应用程序和工具。 MS…

Hive SQL:实现炸列(列转行)以及逆操作(行转列)

目录 列转行行转列 列转行 函数&#xff1a; EXPLODE(ARRAY)&#xff1a;将ARRAY中的每一元素转换为每一行 EXPLODE(MAP)&#xff1a;将MAP中的每个键值对转换为两行&#xff0c;其中一行数据包含键&#xff0c;另一行数据包含值 数据样例&#xff1a; 1、将每天的课程&#…
最新文章