You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在元素内容加载完成后执行函数 服务端加载更多场景实现

问题原因
  • 普通div元素不支持load事件:该事件仅会在window、图片、脚本、iframe这类需要加载独立外部资源的对象上触发,容器div本身没有资源加载逻辑,绑定后永远不会触发。
  • DOMContentLoaded事件仅在页面初始HTML文档解析完成时触发一次,后续动态插入的DOM不会再次触发该事件,绑定在动态容器上完全无效。
  • setTimeout固定延时不可靠:DOM节点插入完成不代表内部图片资源加载完成,此时瀑布流拿不到卡片真实高度就会布局错乱;延时时长设太长又会阻塞交互,没有统一的合适值。
  • 额外代码bug:你当前startIndex变量定义在loadMore函数内部,每次调用都会被重置为0再加5,永远只会拉取第一页的5条数据,需要把变量挪到函数外层。
解决方案

核心逻辑:新条目追加到瀑布流后,等待本次新增的所有图片资源全部加载完成(成功/失败都算),立刻触发布局刷新,不需要固定等待时长。
直接修改对应代码即可:
首先把分页索引挪到函数外层,修正分页逻辑:

let colc, colcUploadedByUser, colcPurchasedByUser;
let searchQuery, filter;
let startIndex = 0; // 挪到函数外层,保留分页进度

然后修改loadMore函数的追加逻辑,替换原有colc.append(itemsToAppend);部分的代码:

const loadMore = async function () {
  startIndex += 5; // 每次调用累加分页值

  const searchQuery = searchForm.querySelector("input").value;
  const filter = searchForm.querySelector("select").value;

  const response = await fetch("load-more", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
      startIndex,
      searchQuery,
      filter,
    }),
  });

  const products = await response.json();

  let itemsToAppend = [];

  products.forEach((product) => {
    const date = new Date(product.createdAt)
      .toISOString()
      .split("T")[0]
      .replaceAll("-", "/");

    const htmlString = `
      <img src="${product.optimizedImgUrl}" data-original-img-source="${product.imgUrl}" alt="article photo" class="articles-container__article-img">
      <h2>${product.title}</h2>
      <p>${product.description} <button class="articles-container__highlight">Read more</button></p>
      <div class="articles-container__article-info separetor"><p>Price: ${product.price} &#36</p><p>Author: ${product.authorName} </p><p>Uploaded: ${date}</p> <p>Resolution: ${product.resolution}</p></div>
      <button class="btn-gray articles-container__button ai-c">Add <img src="img/shopping-cart.svg" alt="shopping cart"></button>
      `;

    const item = document.createElement("article");

    item.className = "ver-spacer grid-item";
    item.setAttribute("id", product._id);
    item.insertAdjacentHTML("beforeend", htmlString);

    itemsToAppend.push(item);
  });

  // 追加新条目到瀑布流
  colc.append(itemsToAppend);

  // 等待本次新增的所有图片加载完成
  const newImages = itemsToAppend.flatMap(item => Array.from(item.querySelectorAll('img')));
  await Promise.all(newImages.map(img => {
    // 图片已经加载过直接返回
    if (img.complete) return Promise.resolve();
    // 监听加载成功/失败事件,失败也不阻塞布局刷新
    return new Promise(resolve => {
      img.addEventListener('load', resolve, { once: true });
      img.addEventListener('error', resolve, { once: true });
    })
  }));

  // 所有图片加载完成,刷新瀑布流布局
  reloadColcade();
};

补充说明:如果你的卡片没有图片、或者高度完全由固定尺寸的内容决定,不需要等图片加载的话,在colc.append(itemsToAppend)之后直接调用reloadColcade()即可。Colcade的append方法本身是同步把DOM插入到列里的,DOM插入完成后就可以直接触发布局计算,之前布局错乱本质是图片加载前高度为0,加载完成后高度撑开但瀑布流没有重新计算导致的。

内容的提问来源于stack exchange,提问作者Oliwier

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 22:09:18