Template、Shadow DOM及Custom Elements 让你创建UI组件比以前更容易了。但是像HTML、CSS、
删除重复依赖也并不简单。例如,现在加载jQuery UI或Bootstrap就需要为
HTML 导入让你以一个合并的HTML文件来加载这些资源。
使用HTML导入
为加载一个HTML文件,你需要增加一个
index.html
- <
link rel="import " href="component.html" >
你可以往HTML导入文件(译者注:本文将“ the
component.html
- <
link rel="stylesheet" href="css/style.css"> - <
script src="js/script .js"></script >
doctype、html、 head、 body这些标签是不需要的。HTML 导入会立即加载要导入的文档,解析文档中的资源,如果有脚本的话也会立即执行它们。
执行顺序
浏览器解析HTML文档的方式是线性的,这就是说HTML顶部的
为了不让
HTML导入文件中的脚本就跟含有defer属性一样。例如在下面的示例中,index.html会先执行
index.html
- <
link rel="import " href="component.html"> // 1. - <title>
Import Example</title> - <
script src="script 3.js"></script > // 4.
component.html
- <
script src="js/script 1.js"></script > // 2. - <
script src="js/script 2.js"></script > // 3.
1.在index.html 中加载component.html并等待执行
2.执行component.html中的
3.执行完
4.执行完
注意,如果给
跨域导入
从根本上说,HTML导入是不能从其他的域名导入资源的。
比如,你不能从http://webcomponents.org/向 http://example.com/ 导入HTML 文件。为了绕过这个限制,可以使用CORS(跨域资源共享)。想了解CORS,请看这篇文章。
HTML导入文件中的window和document对象
前面我提过在导入HTML文件的时候里面的脚本是会被执行的,但这并不意味着HTML导入文件中的标签也会被浏览器渲染。你需要写一些
当在HTML导入文件中使用
index.html
- var
link = document.querySelector('link [rel="import "]'); link .addEventListener('load', function(e) {- var
import edDoc =link .import ; - //
import edDoc points to the document under component.html - });
为了获取component.html中的document 对象,要使用document.current
component.html
- var mainDoc = document.current
Script .ownerDocument; - // mainDoc points to the document under component.html
如果你在用webcomponents.js,那么就用document._current
component.html
- var mainDoc = document._current
Script .ownerDocument; - // mainDoc points to the document under component.html
通过在脚本开头添加下面的代码,你就可以轻松地访问component.html中的document对象,而不用管浏览器是不是支持HTML导入。
document._current
性能方面的考虑
使用HTML 导入的一个好处是能够将资源组织起来,但是也意味着在加载这些资源的时候,由于使用了一些额外的HTML文件而让头部变得过大。有几点是需要考虑的:
解析依赖
假如HTML主文件要依赖多个导入文件,而且导入文件中含有相同的库,这时会怎样呢?例如,你要从导入文件中加载jQuery,如果每个导入文件都含有加载jQuery的
index.html
- <
link rel="import " href="component1.html"> - <
link rel="import " href="component2.html">
component1.html
- <
script src="js/jquery.js"></script >
component2.html
HTML导入自动帮你解决了这个问题。
与加载两次
但这还有一个问题:我们增加了一个要加载的文件。怎么处理数目膨胀的文件呢?幸运的是,我们有一个叫vulcanize的工具来解决这个问题。
合并网络请求
Vulcanize 能将多个HTML文件合并成一个文件,从而减少了网络连接数。你可以借助npm安装它,并且用命令行来使用它。你可能也在用 grunt和gulp 托管一些任务,这样的话你可以把vulcanize作为构建过程的一部分。
为了解析依赖以及合并index.html中的导入文件,使用如下命令:
通过执行这个命令,index.html中的依赖会被解析,并且会产生一个合并的HTML文件,称作 vulcanized.html。学习更多有关vulcanize的知识,请看这儿。
注意:http2的服务器推送功能被考虑用于以后消除文件的连结与合并。
把Template、Shadow DOM、自定义元素跟HTML导入结合起来
让我们对这个文章系列的代码使用HTML导入。你之前可能没有看过这些文章,我先解释一下:Template可以让你用声明的方式定义你的自定义元素的内容。Shadow DOM可以让一个元素的style、ID、class只作用到其本身。自定义元素可以让你自定义HTML标签。通过把这些跟HTML导入结合起来,你自定义的web 组件会变得模块化,具有复用性。任何人添加一个
x-component.html
- <template id="template">
- <style>
- ...
- </style>
- <div id="container">
- <img src="http://webcomponents.org/img/logo.svg">
- <content select="h1"></content>
- </div>
- </template>
- <
script > - // This element will be registered to index.html
- // Because `document` here means the one in index.html
- var XComponent = document.registerElement('x-component', {
- prototype: Object.create(HTMLElement.prototype, {
- createdCallback: {
- value: function() {
- var root = this.createShadowRoot();
- var template = document.querySelector('#template');
- var clone = document.
import Node(template.content, true); - root.appendChild(clone);
- }
- }
- })
- });
- </
script >
index.html
- ...
- <
link rel="import " href="x-component.html"> - </head>
- <body>
- <x-component>
- <h1>This is Custom Element</h1>
- </x-component>
- ...
注意,因为x-component.html 中的document 对象跟index.html的一样,你没必要再写一些棘手的代码,它会自动为你注册。
支持的浏览器
Chrome 和 Opera提供对HTML导入的支持,Firefox要在2014年12月后才支持(Mozilla表示Firefox不计划在近期提供对HTML导入的支持,声称需要首先了解ES6的模块是怎样实现的)。
你可以去chromestatus.com或caniuse.com查询浏览器是否支持HTML导入。想要在其他浏览器上使用HTML导入,可以用webcomponents.js(原名platform.js)。
相关资源
HTML导入就介绍这么多了。如果你想学更多关于HTML导入的知识,请前往:
HTML
HTML