Вам когда-нибудь приходилось манипулировать HTML-документом в JavaScript, но вам было трудно перемещаться по DOM и напрямую изменять элементы? Одним из решений является создание виртуального DOM, облегченного представления структуры HTML в памяти, которое можно легко модифицировать, а затем сравнивать с реальным DOM для внесения минимальных обновлений. В этой статье мы рассмотрим, как создать виртуальный DOM из строки HTML, используя API DOMParser и рекурсивную функцию.

/**
 * Creates a virtual DOM tree from an HTML string.
 *
 * @param {string} htmlString - The HTML string to parse.
 * @return {Object} The root node of the virtual DOM tree.
 */
function createVirtualDOM(htmlString) {
  // Use DOMParser to parse the HTML string into a DOM tree
  const parser = new DOMParser();
  const doc = parser.parseFromString(htmlString, "text/html");
  const rootNode = doc.body;

  /**
   * Recursively creates a virtual DOM node from a DOM element.
   *
   * @param {Element} element - The DOM element to create a virtual node from.
   * @return {Object} The virtual DOM node.
   */
  function createNode(element) {
    // Create a virtual DOM node with the element's tag name and attributes
    const node = {
      tagName: element.tagName,
      attributes: {}
    };

    // Add the element's attributes to the virtual node
    for (let i = 0; i < element.attributes.length; i++) {
      const attribute = element.attributes[i];
      node.attributes[attribute.name] = attribute.value;
    }

    // If the element has child nodes, create virtual nodes for them as well
    if (element.childNodes.length > 0) {
      node.children = [];
      for (let i = 0; i < element.childNodes.length; i++) {
        const child = element.childNodes[i];
        if (child.nodeType === Node.ELEMENT_NODE) {
          // Recursively create a virtual node for the child element
          node.children.push(createNode(child));
        } else if (child.nodeType === Node.TEXT_NODE) {
          // Create a virtual node for the child text node
          node.children.push({
            tagName: null,
            text: child.textContent
          });
        }
      }
    }

    return node;
  }

  // Return the root virtual DOM node
  return createNode(rootNode);
}

Этот метод использует объект DOMParser для анализа строки HTML в дереве DOM, а затем рекурсивно обходит дерево для создания виртуального графа DOM. Виртуальный DOM представлен как вложенный объект, где каждый объект представляет узел DOM и имеет свойство tagName для имени тега узла и свойство attributes для его атрибутов, а также свойство children для его дочерних узлов. Если узел является текстовым узлом, он будет иметь свойство text вместо свойства tagName.

Например, учитывая следующую строку HTML:

<div class="container">
  <p>Hello, world!</p>
</div>

Результирующий виртуальный DOM будет:

{
  tagName: "div",
  attributes: {
    class: "container"
  },
  children: [
    {
      tagName: "p",
      children: [
        {
          tagName: null,
          text: "Hello, world!"
        }
      ]
    }
  ]
}