根据需要在 JavaScript 中解析 HTML 模板

Parse an HTML template as you require it in JavaScript

我在基本的 webpack 配置上花了几个小时,但我仍然无法让它工作。我的目标是在将 html 模板导入到 JavaScript 文件时对其进行解析。它看起来像一个常见的用例,但在我的 webpack 配置或我的理解中应该有一些奇怪的地方。

我查找了 html-loaderhtml-webpack-pluginposthtml 以及 pug 的配置,并且我已经阅读了他们所有的文档,但是 none 他们的工作。

根据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"
          }
        ]
      }
    ]

它没有 return 任何错误,但看起来完全忽略了 posthtml-loader,因为执行 import template from 'src/test.html' 我将模板作为字符串(应该如何做 html-loader一个人)。

根据我的理解,加载程序应该 compile/transform 不同格式的文件并使它们可供 JavaScript 使用,并且由于 html 是前端中最常见的类型project 我以为这很简单,但我在互联网上找不到与此问题相关的任何内容。

我希望有一个 DOM 树对象,或者无论如何,JavaScript 可以使用的东西。

有人能帮我吗?

编辑: 我的问题是关于启动和运行 webpack 配置。我知道很多解析 HTML 字符串的解决方案,但它们在这里不适用

嗯,将字符串转换为 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>

然后您也可以对 'children' 进行转换,就像对普通的 DOM 树对象进行转换一样。

对我来说,posthtml-loader 似乎主要是一个在构建过程中帮助 "prepare" 您的 HTML 的工具。它的解析器选项允许你进入 string -> PostHTML AST Tree 步骤,它的插件选项允许你修改树。然后,它字符串化回 HTML.

我在 webpack 插件中找不到 return 临时树格式的选项。


您可以编写一个小型自定义加载器来将 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 中,你可以告诉 webpack 让 .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 的依赖项,该依赖项仅在浏览器中可用。如果你想在 non-browser 环境中 运行,你可以用 jsdom 之类的东西替换它。

信不信由你,这不是一个常见的用例,将 html 文件导入 JavaScript 并显示它们听起来像是一种解决方法或 mid-port 黑客攻击。 JavaScript 库用于在浏览器中动态生成动态 html 以响应用户输入。如果这是你想要的,你应该使用 React、Vue、Angular、jQuery 或类似的。

正如其他人提到的,解决您问题的方法不是寻找将 HTML 转换为 DOM 节点的加载程序,而是您自己完成。 DOM 直到代码在浏览器中执行后才会出现, 这不是编译时转换。这是一个 run-time 转换。

import template from 'src/test.html'

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

加载程序根本无法完成您的要求。浏览器负责解析 HTML 并根据其平台和供应商特定实现构建 DOM 树。 querySelectorcreateElement 是我们访问此浏览器功能的 API 方法。但是 我们的代码中没有 DOM 个节点 。它们是由平台为我们创建的。我们的 JavaScript 只是在消耗它。

有一些解决方案,例如 DOMParserjsDOM 可以在服务器上执行此操作。但它们是浏览器 DOM 的不完整实现,不应将它们引入 front-end 旨在传送到浏览器的代码中。它们旨在用于无头测试、网络爬虫和其他形式的网页机器消费。

如果您能提出一个特定的场景,您无法在浏览器中将 HTML 字符串与其余代码一起解析,并且就在它被 JavaScript 使用之前,无论如何向我们展示,我们将提出解决方案。但是很有可能你误解了JavaScript、Webpack、HTML的作用以及它们之间的关系

TLDR: HTML 是一个通过 HTTP 发送到浏览器的字符串,浏览器根据它决定如何构建一个 DOM 树供应商特定实施。在前端代码中没有其他选择,只能让浏览器使用您提供的字符串为您构建一个 DOM 树,然后使用 DOM Api.