已接收节点的异步请求与插入

前端开发 2026-07-10
let el = (t, p = {}, ...c) =>
  Object.assign(document.createElement(t),
    p,
    {
      append(...a) {
        return HTMLElement.prototype.append.apply(this, a), this;
      }
    }
  ).append(...c);


const data = {
  // 🔸 Sending a POST request
  j(ms, ok = false) {
    return fetch(document.URL, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json'
      },
      body: JSON.stringify(ms)
    })
    .then(async (response) => {
      const res = await response.json();

      if (res.ms) {
        alert(res.ms);
      } else {
        ok?.(res);
      }
    });
  },

  // 🔸 Initialization
  int() {
    // creating a container
    this.element = el('div', { className: "header" });

    // sending a request
    this.j(
      {news: id_news},       
      (response) => {
        // updating the DOM
        this.element.replaceChildren(
          ...response.map(item =>
            el('div', { textContent: item[1] })
          )
        );
      }
    );
  }
};

// запуск
data.int();

首先我们创建一个容器

this.element = el('div', { className: "header" });

接下来,我们发送请求以接收一个数组,并将得到的数组作为节点插入。

    this.j(
      {news: id_news},
      (response) => {
        // updating the DOM
        this.element.replaceChildren(
          ...response.map(item =>
            el('div', { textContent: item[1] })
          )
        );
      }
    );

问题,我们能立刻这样做吗?

this.element = el('div', { className: "header" }, ...this.j({news: id_news}));

从这个对象开始

this.j()

能从服务器获得响应吗?

目标是在不创建类似下列这样的变量的情况下——

this.element

一旦创建了一个元素,就会把它添加到容器中;当服务器的响应到达时,再添加子节点。无需把它绑定到一个变量…

解决方案

基本上,你希望能够通过某个 elNew 函数创建一个新的元素:

elNew("div", { className: "header" }, ...ExtendedDynamicChildrenOptions);

而不必把上述内容存成例如:this.elHeader =,并且它还接受附加选项,在加载完成后去获取子元素并将它们追加。

如果我们从这两个工具函数开始:

// Utils
const el = (sel, par = document) => par.querySelector(sel);
const elNew = (tag, prop) => Object.assign(document.createElement(tag), prop);

你很快就会明白,你实际需要的是一个 elNewExt——能够从另一个资源获取并创建子元素的能力——基本上是在扩展 elNew 的功能:

// Utils
const el = (sel, par = document) => par.querySelector(sel);
const elNew = (tag, prop) => Object.assign(document.createElement(tag), prop);
const elNewExt = async (tag, prop, opt) => {
  const el = elNew(tag, prop);
  opt.parent?.append(el);
  try {
    const res = await fetch(opt.url, {method: opt.method ?? "GET", body: JSON.stringify(opt.data), headers: {'Content-Type': 'application/json'}});
    if (!res.ok) throw new Error(`Request for children data failed with status ${res.status}`);
    const data = (await res.json()).slice(opt.from, opt.to);
    el.innerHTML = ""; // Clear existing content
    el.append(...data.map(opt.children));
  } catch (err) {
    console.error(err.message);
  }
  return el;
};

// App
const app = {
  init() {
    elNewExt("div", {
      className: "header",
      textContent: "Loading..."
    }, /* Ext options: */ {
      url: "https://jsonplaceholder.typicode.com/posts",
      to: 3, // get first N items
      children: (ch, i) => elNew("div", { className: "child", textContent: `${i+1}: ${ch.title}` }),
      parent: el("body"),
    });
  }
};

// Launch
app.init();
.child { outline: 1px solid red; }
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章