Разберите HTML-шаблон так, как вам нужно, в JavaScript

Я потратил часы на базовую конфигурацию веб-пакета, но до сих пор не могу заставить его работать. Моя цель - выполнить синтаксический анализ шаблона html, когда вы импортируете его в файл JavaScript. Это похоже на обычный вариант использования, но в моей конфигурации веб-пакета или в моем понимании должно быть что-то странное.

Я искал конфигурации html-loader, html-webpack-plugin, posthtml, а также pug, и я прочитал всю их документацию, но ни одна из них не сработала.

Согласно PostHTML Readme:

PostHTML is a tool for transforming HTML/XML with JS plugins. PostHTML itself is very small. It includes only a HTML parser, a HTML node tree API and a node tree stringifier.

Итак, поскольку это было наиболее многообещающе, я сообщаю о своей попытке с posthtml:

   rules: [
      {
        test: /.html$/,
        use: [
          {
            loader: "html-loader",
            options: {
              minimize: true,
              interpolation: false
            }
          },
          {
            loader: "posthtml-loader"
          }
        ]
      }
    ]

Он не возвращает никакой ошибки, но похоже, что он полностью игнорирует posthtml-loader, так как при выполнении import template from 'src/test.html' я получаю шаблон в виде строки (как предполагается делать html-loader отдельно).

Насколько я понимаю, загрузчики должны компилировать/преобразовывать файлы разных форматов и делать их доступными для JavaScript, а поскольку html является наиболее распространенным типом во внешнем проекте, я полагал, что это было легко, но я ничего не нашел на интернет по этому вопросу.

Чего я ожидаю, так это иметь объект дерева DOM или, во всяком случае, что-то, что может использоваться JavaScript.

Кто-нибудь может мне помочь?

Обновлено: Мой вопрос касается настройки и работы веб-пакета. Я знаю много решений для разбора строк HTML, но здесь они не применимы.

Первая строка в документе html-loader: Exports HTML as string, можете ли вы дать ссылку на то, что posthml-loader есть/делает?

HRK44 31.05.2019 10:28

Вы добавили часть plugin из их документов в веб-пакете?

HRK44 31.05.2019 10:46

Попробуй ssr и отреагируй, в моей папке все готово к работе. это просто github.com/Da99er/реагировать-сервер-старт-кит

Vadim Hulevich 31.05.2019 10:53

@HRK44 Да, здесь — это мой полный webpack.config.js

Cristian Traìna 31.05.2019 10:58

@VadimHulevich это не то, что я хочу, я не могу использовать никакой фреймворк (иначе я не сошел с ума от webpack :D) и, в конце концов, все, что я хочу, это просто выполнить innerHTML. Так что любой фреймворк, даже маленький, будет излишним.

Cristian Traìna 31.05.2019 10:59
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
5
5
1 819
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Что ж, преобразовать строку в html легко. Поэтому, если вы получите строковый ответ для своего шаблона, вы можете преобразовать его в структуру DOM, как показано ниже.

/** Create a NON attached DOM element. This floats in nothing. Hello Dave */
var dave = document.createElement("div");

/** Give dave a body with the HTML string we received from "somewhere" */
dave.innerHTML = "<div class='foo'><input type='text'></div>";

/**
  * dave is now <div><div class='foo'><input type='text'></div></div>
  */
dave.querySelector('input').value = "I'm sorry Dave, I'm afraid I can't do that";


/** ======================================================================
 * Now render we render Dave, this isn't really needed, but will do anyways.
 * We don't need the "wrapping" floating div we created so we get all of Dave's children
 * And let Dave be forgotten about in the abyss of eternity.
 */
var content = dave.children;

var main = document.getElementById('main');
for(var i = 0; i < content.length; i++) {
  main.appendChild(content[i]);
}
.foo {
   background-color: red;
}
.foo input {
   background-color: black;
   color: white;
}
<body id = "main">
</body>

Затем вы можете выполнить преобразование и для «детей», как и для обычного объекта дерева DOM.

Мне не нравится это решение, потому что мне нужно парсить html в нескольких файлах, и я не могу каждый раз вводить html в DOM только для того, чтобы понять, как устроен шаблон. Я мог бы создать поддельный документ, поскольку это позволяет JavaScript, а затем использовать его для анализа. Или я мог бы использовать отдельную библиотеку. Но я бы предпочел решение на основе веб-пакета: D, теоретически оно должно работать.

Cristian Traìna 31.05.2019 11:22

@ChristianTra&#236;na Вам не нужно вводить в DOM. только последняя строка внедряется в DOM. остальное чисто виртуально. Вы создаете виртуальный неприкрепленный элемент с помощью x. Там вы вставляете текст. Это преобразовано в объект DOM. Вы можете сделать x.getElementById и т. д. Без вступления в силу визуализированного DOM

Tschallacka 31.05.2019 11:25

@CristianTraìna Я изменил ответ, добавив несколько комментариев, чтобы объяснить, что происходит.

Tschallacka 31.05.2019 11:42
Ответ принят как подходящий

Мне кажется, что posthtml-loader — это в первую очередь инструмент, который помогает «подготовить» ваш HTML во время сборки. Параметры его парсера позволяют перейти к шагу string -> PostHTML AST Tree, а параметры плагина позволяют изменять дерево. Затем он преобразуется обратно в HTML.

Я не смог найти в плагине веб-пакета возможность вернуть промежуточный формат дерева.


Вы можете написать небольшой пользовательский загрузчик для разбора строк HTML в объекты DOM:

// custom-loader.js
module.exports = function(content) {
  return `module.exports = (function() {
    const parser = new DOMParser();
    const doc = parser.parseFromString("${content}", "text/html");
    return doc.body.children; 
  }())`;
};

Затем в своем webpack.config.js вы можете указать веб-пакету, чтобы .html файлы передавали этот загрузчик:

// webpack.config.js
module.exports = {
  mode: 'development',
  entry: './main.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'main.bundle.js'
  },
  devtool: "eval-source-map",
  module: {
    rules: [
      {
        test: /\.html$/,
        use: [ './custom-loader' ]
      }
    ]
  }
};

Теперь всякий раз, когда вы вводите что-то вроде const template = require('./template.html');, вы получите экземпляр HTMLCollection, а не просто строку.


Обратите внимание, что этот загрузчик добавляет зависимость к DOMParser, которая доступна только в браузере. Вы можете заменить его чем-то вроде jsdom, если хотите работать в небраузерной среде.

Вы не только объяснили, почему PostHTML не работает, но и предложили рабочее решение. Так что большое спасибо, это, безусловно, лучший ответ. Вы бы посоветовали этому решению реализовать структуру модель-представление-контроллер (без фреймворка) или вы думаете, что есть лучшие решения?

Cristian Traìna 02.06.2019 11:19

Я думаю, что это отличная идея — импортировать ваши HTML-шаблоны с помощью webpack. Я использую тот же подход при работе с Knockout.js в MVVM, например, в моде. Удобно, когда модели (просмотра), шаблоны и даже стили хорошо разделены. Тем не менее, автоматический анализ элементов DOM я мог бы с таким же успехом рассматривать как часть вашего кода на стороне клиента. Типа, new UserProfile( apiUser, Template.fromString(require("./UserProfile.html") ) ).

user3297291 03.06.2019 09:54

Хотите верьте, хотите нет, но это не самый распространенный вариант использования, но импорт html-файлов в JavaScript и их отображение звучит как обходной путь или взлом среднего порта. Библиотеки JavaScript используются для генерации динамического html "на лету" в браузере в ответ на вводимые пользователем данные. Если это то, что вы хотите, вы должны использовать React, Vue, Angular, jQuery или что-то подобное.

Как уже упоминалось, решение вашей проблемы состоит не в том, чтобы искать загрузчик, который преобразует HTML в узел DOM, а в том, чтобы вы сделали это самостоятельно. DOM отсутствует, пока код не будет выполнен в браузере,Это не преобразование времени компиляции. Это преобразование во время выполнения.

import template from 'src/test.html'

const html = document.createElement('div')
html.innerHTML = template

Загрузчик просто не может сделать то, что вы просите. Браузер отвечает за синтаксический анализ HTML и построение дерева DOM на основе своей платформы и конкретной реализации поставщика. querySelector или createElement — это методы API для доступа к этой функции браузера. Но у нас нет узлов DOM в нашем коде. Они созданы для нас платформой. Наш JavaScript просто потребляет его.

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

Если вы можете представить конкретный сценарий, в котором вы не можете проанализировать строку HTML в браузере вместе с остальным кодом и непосредственно перед тем, как она будет использована JavaScript, во что бы то ни стало покажите нам, и мы предложим решение. Но весьма вероятно, что вы неправильно поняли роли JavaScript, Webpack и HTML и взаимосвязь между ними.

TLDR: HTML — это строка, которая отправляется в браузер через HTTP, и браузер решает, как построить дерево DOM на основе его конкретной реализации поставщика. Во внешнем коде нет альтернативы, кроме как заставить браузер построить для вас дерево DOM с предоставленной вами строкой, а затем использовать его с помощью DOM Api.

Спасибо за ваш ответ. Я думал, что есть что-то доступное для анализа HTML, например, фреймворк, поскольку Angular, React, Vue и так далее основаны на веб-пакете, и я думал, что все они используются для анализа и составления шаблонов. Вместо этого, вероятно, каждый из них использует свой собственный парсер

Cristian Traìna 02.06.2019 11:16

Они используют свои собственные компиляторы для создания своих собственных представлений объектов, таких как React.createElement('div', childElements) и т. д.... Ни одна из платформ фактически не создает DOM до тех пор, пока код не будет выполнен в браузере.

Avin Kavish 02.06.2019 11:21

Другие вопросы по теме