能否在多个页面上重用HTML作为模板?

29

我在网站上有几个页面,它们都使用相同的页眉。我想知道是否有一种方法可以简单地引用一个包含页眉HTML的文件,就像这个伪代码:

<!-- Main Page -->

<body>
  <html_import_element src = "myheadertemplate.html">
<body>

然后在另一个文件中:

<!-- my header template html -->

<div>
  <h1>This is my header</h1>
  <div id = "navbar">
    <div class = "Tab">Home</div>
    <div class = "Tab">Contact</div>
  </div>
</div>

我希望能够编写一次头部HTML代码,然后通过编写一个简单的标签,在每个需要它的页面中导入它。这种方法可行吗?我可以使用XML吗?


但是大多数服务器端语言都支持某种类型的“包含”功能。您将在哪个服务器上托管您的网站?(您也可以使用JS来实现,但这不利于搜索引擎优化 - Gabriele Petrioli
underscorejs对于这样的事情来说太大了,一个简单的ajax请求就足够了...在jquery中,它看起来像这样:$.get("header.htm", function(data) {$("#header").html(data);}); - seahorsepip
我只是想知道是否有一个元素可以处理这个。很遗憾,没有。 - Felix Kling
1
@FelixKling 技术上说,你是错误的,框架元素实际上过去就是为了这个目的而制作的,但现在已被弃用,因为服务器端代码是更好的方法。 - seahorsepip
1
@seahorsepip:你说得对,我完全忘记了框架...但是是的,我们不想建议过时的功能,所以“不”仍然既正确又不正确:P - Felix Kling
显示剩余6条评论
4个回答

15

你可以按照以下方式完成。

<head>
  <link rel="import" href="myheadertemplate.html">
</head>

您可以在此处使用myheadertemplate.html文件。

<div>
  <h1>This is my header</h1>
  <div id = "navbar">
    <div class = "Tab">Home</div>
    <div class = "Tab">Contact</div>
  </div>
</div>

然后你可以在下面的JS中使用它

var content = document.querySelector('link[rel="import"]').import;

1
一个ajax请求更有意义,因为上面只有html5:/ 不过代码很好,我自己从来不知道import超出了css import ^^ - seahorsepip
1
我曾经在探索WebComponents和高级HTML5时遇到过这个。 - Shadab K
1
实际上,这正是我正在寻找的。前沿的答案!我在这里找到了一个很好的解释:[链接](http://www.html5rocks.com/en/tutorials/webcomponents/imports/) - Frank
哇,这是一个很棒的仅前端解决方案。我在 Stack Overflow 相关问题中从未看到其他人发布过这种方法。不确定是否有遗漏,但我不需要 JS 部分就可以让它工作。 - akmalmzamri
14
请注意,此行为已经被弃用,不应再使用: https://caniuse.com/#feat=imports - Dave Powers

12

所以,经过很长时间的尝试,我终于找到了一种使用 AJAX 的方法。HTML 导入是一个很好的解决方案,但截至 2017 年 4 月,浏览器支持严重不足,因此我想出了更好的解决方案。这是我的源代码:

function HTMLImporter() {}

HTMLImporter.import = function (url) {
  var error, http_request, load, script;

  script =
    document.currentScript || document.scripts[document.scripts.length - 1];

  load = function (event) {
    var attribute, index, index1, new_script, old_script, scripts, wrapper;

    wrapper = document.createElement("div");
    wrapper.innerHTML = this.responseText;

    scripts = wrapper.getElementsByTagName("SCRIPT");

    for (index = scripts.length - 1; index > -1; --index) {
      old_script = scripts[index];

      new_script = document.createElement("script");
      new_script.innerHTML = old_script.innerHTML;

      for (index1 = old_script.attributes.length - 1; index1 > -1; --index1) {
        attribute = old_script.attributes[index1];
        new_script.setAttribute(attribute.name, attribute.value);
      }

      old_script.parentNode.replaceChild(new_script, old_script);
    }

    while (wrapper.firstChild) {
      script.parentNode.insertBefore(
        wrapper.removeChild(wrapper.firstChild),
        script
      );
    }

    script.parentNode.removeChild(script);

    this.removeEventListener("error", error);
    this.removeEventListener("load", load);
  };

  error = function (event) {
    this.removeEventListener("error", error);
    this.removeEventListener("load", load);

    alert("there was an error!");
  };

  http_request = new XMLHttpRequest();
  http_request.addEventListener("error", error);
  http_request.addEventListener("load", load);
  http_request.open("GET", url);
  http_request.send();
};
现在,当我想将 HTML 导入到另一个文档中时,我只需要添加这样的脚本标签:
<script>HTMLImporter.import("my-template.html");</script>

我的函数会用my-template.html的内容替换调用导入的脚本标签,并执行在模板中找到的任何脚本。 模板不需要特殊格式,只需编写要在代码中显示的HTML即可。


但是您需要将脚本添加到每个想要重用<head>的文件中,对吗?我认为真正管理您想要做的事情的唯一方法是实现具有动态网页的站点,其中服务器根据正确的模板即时生成页面。 - guero64
@guero64 你可以将脚本放入一个单独的文件中,并使用带有src="sepFile.js"的脚本标签。然后,您只需要在每个HTML文件中添加两个脚本标签即可。我不会测试这个,因为我更愿意使用后端解决方案,但我相信它应该可以工作。 - Arnold Cross

0
据我所知,这是不可能的。但你可以在 iframe 元素中加载头部作为网页。过去,网页是使用框架元素构建的,以加载网页的不同部分,但这已不被推荐,并且当前浏览器的支持也是由于遗留问题。
在大多数情况下,这是通过服务器端语言(如 PHP)完成的,例如 include("header.php");

但所有的代码都将是HTML,因此没有动态内容。我正在使用NodeJS,所以我想这不会很难,但它似乎是一些非常简单的功能,所以我希望它可能已经存在。 - Frank
我相信您也可以使用<object>标签来插入HTML,而无需使用iframe。 - GillesC
对象标签在这种情况下的工作方式与iframe标签基本相同,仅受现代浏览器支持。 - seahorsepip
1
我认为在HTML本身中没有意义,因为HTML是一种纯文本XML语言,不应该是动态的,所以像<get data="header.html">这样的东西不应该被替换为header.html的HTML内容。@Frank - seahorsepip

0
我找到了这个解决方案。 在每个页面上,我添加了以下脚本:

<script type="module" src="main.js"></script>

和标签

<common-header></common-header>.

一切都运作得非常完美。 我不知道它是否非常高效和有效。
    ....some code...
        <script type="module" src="main.js"></script>
    </head>
    <body>
    <common-header></common-header>

main.js:

class CommonHeader extends HTMLElement {
  
connectedCallback(){
    this.innerHTML = `
    <div class="header">
        <div class="logo">
            <img class="img" src="assets/Logo2.png" alt="logo" />
        </div>
        <ul class="menu">
        <li><a href="./index.html" class="">Home</a></li>
        <li><a href="./single.html" class="">Single</a></li>
        <li><a href="./contact.html" class="">Contact</a></li>
        </ul>
        <div class="cta">
            <a href="" class="button">Chiamami </a>
        </div>
        <div class="hamburger"><span></span><span></span><span></span> 
        </div>
  </div> `
    }
}
customElements.define('common-header', CommonHeader)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接