outerHTML完成代码,是个怎么着的东西

HTML 自定义元素教程

2017/06/22 · HTML5 ·
outerHTML完成代码,是个怎么着的东西。自定义元素

原文出处:
阮一峰   

零件是 Web 开发的自由化,现在的热点是 JavaScript 组件,可是 HTML
组件将来也许更有期望。

正文就介绍 HTML 组件的基础知识:自定义元素(custom elements)。

澳门葡京 1

一、浏览器处理

大家一般都利用标准的 HTML 元素。

XHTML

<p>Hello World</p>

1
<p>Hello World</p>

上面代码中,“

“就是正统的 HTML 元素。

一经利用非标准的自定义元素,会有如何结果?

XHTML

<greeting>Hello World</greeting>

1
<greeting>Hello World</greeting>

地方代码中,`就是非标准元素,浏览器不认识它。这段代码的[运行结果](http://jsbin.com/rifozonomu/edit?html,output)是,浏览器照常显示Hello World`,那阐明浏览器并不曾过滤这几个元素。

澳门葡京 2

现今,为自定义元素加上样式。

JavaScript

greeting { display: block; font-size: 36px; color: red; }

1
2
3
4
5
greeting {
  display: block;
  font-size: 36px;
  color: red;
}

运作结果如下。

澳门葡京 3

继而,使用脚本操作那几个元素。

JavaScript

function customTag(tagName, fn){ Array
.from(document.getElementsByTagName(tagName)) .forEach(fn); } function
greetingHandler(element) { element.innerHTML = ‘你好,世界’; }
customTag(‘greeting’, greetingHandler);

1
2
3
4
5
6
7
8
9
10
11
function customTag(tagName, fn){
  Array
    .from(document.getElementsByTagName(tagName))
    .forEach(fn);
}
 
function greetingHandler(element) {
  element.innerHTML = ‘你好,世界’;
}  
 
customTag(‘greeting’, greetingHandler);

运作结果如下。

澳门葡京 4

那表明,浏览器对待自定义元素,就好像对待专业元素一样,只是没有默许的样式和表现。那种处理方式是写入
HTML5
标准的。

“User agents must treat elements and attributes that they do not
understand as semantically neutral; leaving them in the DOM (for DOM
processors), and styling them according to CSS (for CSS processors),
but not inferring any meaning from them.”

地方那段话的意思是,浏览器必须将自定义元素保留在 DOM
之中,但不会别的语义。除此之外,自定义元素与规范元素都如出一辙。

实际上,浏览器提供了一个HTMLUnknownElement对象,所有自定义元素都是该目的的实例。

JavaScript

var tabs = document.createElement(‘tabs’); tabs instanceof
HTMLUnknownElement // true tabs instanceof HTMLElement // true

1
2
3
4
var tabs = document.createElement(‘tabs’);
 
tabs instanceof HTMLUnknownElement // true
tabs instanceof HTMLElement // true

地点代码中,tabs是一个自定义元素,同时继续了HTMLUnknownElementHTMLElement接口。

Web Components 是个什么的东西

2016/09/04 · HTML5,
JavaScript · Web
Components

初稿出处: teabyii   

前者组件化那些主旨相关的内容已经火了很久很久,angular 刚出去时的
Directive 到 angular2 的 components,还有 React 的components
等等,无一不是前端组件化的一种完成和讨论,可是提上议程的 Web Components
标准是个什么的东西,相关的有些框架或者类库,如 React,Angular2,甚至是
x-tag,polymer 现在落到实处的组件化的东西和 Web Components
标准差异在哪儿?我花时间努力地把现有的 W3C Web
Components
文档看了下,然后坚强地写下那么些记录。

第一我们须求领悟,Web Components 包蕴了几个部分:

  • Custom Elements
  • HTML Imports
  • HTML
    Templates
  • Shadow DOM

这四局地有机地整合在一齐,才是 Web Components。

可以用自定义的标签来引入组件是前者组件化的根底,在页面引用 HTML 文件和
HTML 模板是用以帮忙编写组件视图和零部件资源管理,而 Shadow DOM
则是隔离组件间代码的争辨和震慑。

上边分别是每一有些的笔记内容。

缩减DOM数可以加速浏览器的在分析页面过程中DOM Tree和render
tree的营造,从而抓实页面品质。为此大家得以把页面中那么些首屏渲染不可知的片段HTML暂存在TextArea中,等成功渲染后再处理那有些HTML来完成这么些目标。
要把TextArea
中暂存的HTML内容添加到页面中,使用要素的outerHTML属性是最简易方便的了,可是在DOM标准中并从未定义outerHTML,帮忙的浏览器有IE6+,safari,
operal和 Chrome,经测试FF4.0-
中还不协助。所以我们就来落到实处一个方可跨浏览器的outerHTML。
outerHTML 就是取得或安装包括元素标签自己在内的html。上边是已毕代码:

HTML imports 入门

2015/02/10 · HTML5 ·
HTML,
imports

本文由 伯乐在线 –
XfLoops
翻译,周进林
校稿。未经许可,禁止转载!
英文出处:webcomponents.org。欢迎插足翻译组。

Template、Shadow
DOM及Custom
Elements 让你创造UI组件比原先更便于了。不过像HTML、CSS、JavaScript那样的资源依旧需求一个个地去加载,那是很没功能的。

删去重复看重也并不简单。例如,现在加载jQuery
UI或Bootstrap就须求为JavaScript、CSS及Web
Fonts添加单独的标签。倘诺您的Web
组件应用了密密麻麻的借助,那事情就变得越来越复杂。

HTML 导入让你以一个集合的HTML文件来加载那一个资源。

二、HTML import

有了自定义元素,就足以写出语义性分外好的 HTML 代码。

XHTML

<share-buttons> <social-button type=”weibo”> <a
href=”…”>微博</a> </social-button> <social-button
type=”weixin”> <a href=”…”>微信</a>
</social-button> </share-buttons>

1
2
3
4
5
6
7
8
<share-buttons>
  <social-button type="weibo">
    <a href="…">微博</a>
  </social-button>
  <social-button type="weixin">
    <a href="…">微信</a>
  </social-button>
</share-buttons>

上面的代码,一眼就能观察语义。

如果将`元素的样式与脚本,封装在一个 HTML
文件
share-buttons.html`之中,那个因素就足以复用了。

利用的时候,先引入share-buttons.html

<link rel=”import” href=”share-buttons.html”>

1
<link rel="import" href="share-buttons.html">

下一场,就足以在网页中行使“了。

XHTML

<article> <h1>Title</h1> <share-buttons/> …
… </article>

1
2
3
4
5
<article>
  <h1>Title</h1>
  <share-buttons/>
  … …
</article>

HTML imports
的更加多用法可以参见教程(1,2)。近期唯有Chrome 浏览器接济这么些语法。

Custom Elements

复制代码 代码如下:

使用HTML导入

为加载一个HTML文件,你必要追加一个link标签,其rel属性为import,herf属性是HTML文件的途径。例如,如若您想把component.html加载到index.html:

index.html

XHTML

<link rel=”import” href=”component.html” >

1
<link rel="import" href="component.html" >

您可以往HTML导入文本(译者注:本文将“ the imported
HTML”译为“HTML导入文本”,将“the original
HTML”译为“HTML主文件”。例如,index.html是HTML主文件,component.html是HTML导入文本。)添加任何的资源,包蕴剧本、样式表及字体,就跟往普通的HTML添加资源均等。

component.html

XHTML

<link rel=”stylesheet” href=”css/style.css”> <script
src=”js/script.js”></script>

1
2
<link rel="stylesheet" href="css/style.css">
<script src="js/script.js"></script>

doctype、html、 head、 body那一个标签是不必要的。HTML
导入会马上加载要导入的文档,解析文档中的资源,如果有脚本的话也会即时执行它们。

三、Custom Elements 标准

HTML5 标准规定了自定义元素是合法的。然后,W3C
就为自定义元素制定了一个独门的 Custom Elements
标准。

它与其他三个正经放在一起—- HTML Imports,HTML Template、Shadow
DOM—-统称为 Web
Components
规范。近期,这么些专业唯有 Chrome
浏览器支持。

澳门葡京 5

Custom Elements
标准对自定义元素的名字做了限制。

“自定义元素的名字务必含有一个破折号(-)所以都是正确的名字,而和“是不得法的。那样的界定使得
HTML 解析器可以识别那个是专业元素,哪些是自定义元素。”

澳门葡京 6

留意,一旦名字之中使用了破折号,自定义元素就不是HTMLUnknownElement的实例了。

JavaScript

var xTabs = document.createElement(‘x-tabs’); xTabs instanceof
HTMLUnknownElement // false xTabs instanceof HTMLElement // true

1
2
3
4
var xTabs = document.createElement(‘x-tabs’);
 
xTabs instanceof HTMLUnknownElement // false
xTabs instanceof HTMLElement // true

Custom Elements 标准规定了,自定义元素的概念可以采取 ES6
class语法。

JavaScript

// 定义一个 class MyElement extends HTMLElement {…}
window.customElements.define(‘my-element’, MyElement);

1
2
3
// 定义一个
class MyElement extends HTMLElement {…}
window.customElements.define(‘my-element’, MyElement);

地点代码中,原生的window.customElements对象的define方法用来定义
Custom
Element。该措施接受多个参数,首个参数是自定义元素的名字,第一个参数是一个
ES6 的class

这个class使用getset艺术定义 Custom Element 的某部属性。

JavaScript

class MyElement extends HTMLElement { get content() { return
this.getAttribute(‘content’); } set content(val) {
this.setAttribute(‘content’, val); } }

1
2
3
4
5
6
7
8
9
class MyElement extends HTMLElement {
  get content() {
    return this.getAttribute(‘content’);
  }
 
  set content(val) {
    this.setAttribute(‘content’, val);
  }
}

有了那个概念,网页之中就足以插入“了。

JavaScript

<my-element content=”Custom Element”> Hello </my-element>

1
2
3
<my-element content="Custom Element">
  Hello
</my-element>

处理脚本如下。

JavaScript

function customTag(tagName, fn){ Array
.from(document.getElementsByTagName(tagName)) .forEach(fn); } function
myElementHandler(element) { element.textConent = element.content; }
customTag(‘my-element’, myElementHandler);

1
2
3
4
5
6
7
8
9
10
11
function customTag(tagName, fn){
  Array
    .from(document.getElementsByTagName(tagName))
    .forEach(fn);
}
 
function myElementHandler(element) {
  element.textConent = element.content;
}
 
customTag(‘my-element’, myElementHandler);

运行结果如下。

澳门葡京 7

ES6 Class 的一个利益是,可以很简单地写出继承类。

JavaScript

class MyNewElement extends MyElement { // … }
customElements.define(‘my-new-element’, MyNewElement);

1
2
3
4
5
class MyNewElement extends MyElement {
  // …
}
 
customElements.define(‘my-new-element’, MyNewElement);

今天的科目就到那边,越多用法请参考谷歌(Google)的官方教程。

概述

Custom Elements 顾名思义,是提供一种方式让开发者可以自定义 HTML
元素,包含特定的重组,样式和作为。襄助 Web Components
标准的浏览器会提供一文山会海 API
给开发者用于成立自定义的要素,或者增添现有元素。

这一项专业的草案还地处不安定的情状,时有更新,API
还会怀有转变,上面的笔记以 Cutsom Elements
2016.02.26
这一个本子为准,因为在新式的 chrome 浏览器已经是可以干活的了,那样可以选用demo 来做尝试,最后我会再简单写一下风行文档和那个的分裂。

if(typeof HTMLElement !== “undefined” && !(“outerHTML” in
HTMLElement.prototype)) {
//console.log(“defined outerHTML”);
HTMLElement.prototype.__defineSetter__(“outerHTML”,function(str){
var fragment = document.createDocumentFragment();
var div = document.createElement(“div”);
div.innerHTML = str;
for(var i=0, n = div.childNodes.length; i<n; i++){
fragment.appendChild(div.childNodes[i]);
}
this.parentNode.replaceChild(fragment, this);
});
//
HTMLElement.prototype.__defineGetter__(“outerHTML”,function(){
var tag = this.tagName;
var attributes = this.attributes;
var attr = [];
//for(var name in attributes){//遍历原型链上成员
for(var i=0,n = attributes.length; i<n; i++){//n指定的性质个数
if(attributes[i].specified){
attr.push(attributes[i].name + ‘=”‘ + attributes[i].value + ‘”‘);
}
}
return ((!!this.innerHTML) ?
‘<‘ + tag + ‘ ‘ + attr.join(‘
‘)+’>’+this.innerHTML+'</’+tag+’>’ :
‘<‘ + tag + ‘ ‘ +attr.join(‘ ‘)+’/>’);
});
}

施行各类

浏览器解析HTML文档的法门是线性的,那就是说HTML顶部的script会比底部先实施。并且,浏览器平常会等到JavaScript代码执行达成后,才会随着分析前面的代码。

为了不让script 妨碍HTML的渲染,你可以在标签中添加async或defer属性(或者您也足以将script 标签放到页面的最底层)。defer 属性会延迟脚本的施行,直到所有页面解析落成。async 属性让浏览器异步地履行脚本,从而不会妨碍HTML的渲染。那么,HTML
导入是何许工作的啊?

HTML导入文本中的脚本就跟含有defer属性一样。例如在上边的示范中,index.html会先举办script1.js和script2.js
,然后再履行script3.js。

index.html

XHTML

<link rel=”import” href=”component.html”> // 1.
<title>Import Example</title> <script
src=”script3.js”></script> // 4.

1
2
3
<link rel="import" href="component.html"> // 1.
<title>Import Example</title>
<script src="script3.js"></script>        // 4.

component.html

XHTML

<script src=”js/script1.js”></script> // 2. <script
src=”js/script2.js”></script> // 3.

1
2
<script src="js/script1.js"></script>     // 2.
<script src="js/script2.js"></script>     // 3.

1.在index.html 中加载component.html并等待执行

2.执行component.html中的script1.js

3.执行完script1.js后执行component.html中的script2.js

4.实施完 script2.js继而执行index.html中的script3.js

注意,如果给link[rel=”import”]添加async属性,HTML导入会把它看成含有async属性的脚本来对待。它不会等待HTML导入文本的实践和加载,那代表HTML
导入不会妨碍HTML主文件的渲染。那也给提拔网站质量带来了也许,除非有其余的剧本依赖于HTML导入文本的执行。

四、参考链接

  • John Negoita, Extending HTML by Creating Custom
    Tags
  • StackOverflow, Are custom elements valid
    HTML5?
  • Eric Bidelman, Custom Elements v1: Reusable Web
    Components

 

1 赞 1 收藏
评论

澳门葡京 8

registerElement

第一,我们可以尝试在 chrome 控制台输入
HTMLInputElement,可以看来是有这么一个事物的,这一个通晓为 input DOM
元素实例化时的构造函数,基础的是 HTMLElement

Web Components 标准提议提供那样一个接口:

JavaScript

document.registerElement(‘x-foo’, { prototype:
Object.create(HTMLElement.prototype, { createdCallback: { value:
function() { … } }, … }) })

1
2
3
4
5
6
7
8
document.registerElement(‘x-foo’, {
  prototype: Object.create(HTMLElement.prototype, {
    createdCallback: {      
      value: function() { … }
    },
    …
  })
})

您可以运用 document.registerElement 来注册一个标签,标准中为了提供
namesapce 的支撑,幸免争辨,规定标签类型(也足以知道为名字)必要选择 -
连接。同时,不可能是以下那部分:

  • annotation-xml
  • color-profile
  • font-face
  • font-face-src
  • font-face-uri
  • font-face-format
  • font-face-name
  • missing-glyph

首个参数是标签相关的布置,首要是提供一个 prototype,那么些原型对象是以
HTMLElement 等的原型为根基创设的靶子。然后您便足以在 HTML
中去采纳自定义的标签。如:

XHTML

<div> <x-foo></x-foo> </div>

1
2
3
<div>
  <x-foo></x-foo>
</div>

是或不是嗅到了 React 的味道?好吧,React 说它自己根本不是做那几个工作的。

代码表达:
1
代码中率先条件判断来监测浏览器是或不是帮忙outerHTML以幸免覆盖浏览器原生的贯彻。
2 “__defineSetter__”,”__defineGetter__”
是firefox浏览器私有方面。分别定义当设置属性值和得到属性要实施的操作。
3 在”__defineSetter__”
“outerHTML”中为了防止插入页面中元素过多导致频仍暴发reflow影响属性。使用了文档碎片对象fragment来暂存要求插入页面中DOM元素。
4 在”__defineGetter__” “outerHTML”
中使用要素attributes属性来遍历给元素指定的习性。结合innerHTML重临了包涵原属本身在内的html字符串。
测试代码:

跨域导入

从根本上说,HTML导入是不可以从任何的域名导入资源的。

譬如说,你不能够从向 
导入HTML
文件。为了绕过那个界定,可以行使CORS(跨域资源共享)。想打听CORS,请看那篇文章。

生命周期和回调

在那些 API 的底子上,Web Components
标准提供了一多级决定自定义元素的法子。大家来挨家挨户看下:

一个自定义元素会经历以下这个生命周期:

  • 登记前创办
  • 挂号自定义元素定义
  • 在登记后创设元素实例
  • 要素插入到 document 中
  • 元素从 document 中移除
  • 要素的属性变化时

本条是很要紧的始末,开发者可以在登记新的自定义元素时指定相应的生命周期回调来为自定义元素添加各类自定义的一坐一起,那些生命周期回调包罗了:

  • createdCallback
    自定义元素注册后,在实例化之后会调用,平时多用来做元素的起始化,如插入子元素,绑定事件等。
  • attachedCallback
    要素插入到 document 时接触。
  • detachedCallback
    要素从 document 中移除时接触,可能会用于做类似 destroy 之类的作业。
  • attributeChangedCallback
    要素属性变化时接触,可以用来从外到内的通讯。外部通过修改元素的特性来让内部获得有关的数量同时实施相应的操作。

其两回调在分歧情状下有对应分化的参数:

  • 安装属性时,参数列表是:属性名称,null,值,命名空间
  • 修改属性时,参数列表是:属性名称,旧值,新值,命名空间
  • 去除属性时,参数列表是:属性名称,旧值,null,命名空间

好了,就下面驾驭到的底子上,如若我们要开创一个自定义的 button-hello
按钮,点击时会 alert('hello world'),代码如下:

JavaScript

document.registerElement(‘button-hello’, { prototype:
Object.create(HTMLButtonElement.prototype, { createdCallback: { value:
function createdCallback() { this.innerHTML = ‘<button>hello
world</button>’ this.addEventListener(‘click’, () => {
alert(‘hello world’) }) } } }) })

1
2
3
4
5
6
7
8
9
10
11
12
document.registerElement(‘button-hello’, {
  prototype: Object.create(HTMLButtonElement.prototype, {
    createdCallback: {
      value: function createdCallback() {
        this.innerHTML = ‘<button>hello world</button>’
        this.addEventListener(‘click’, () => {
          alert(‘hello world’)
        })
      }
    }
  })
})

要小心上述代码执行之后才能运用 <button-hello></button-hello>

复制代码 代码如下:

HTML导入文本中的window和document对象

前边我提过在导入HTML文件的时候里面的脚本是会被实施的,但这并不意味HTML导入文本中的标签也会被浏览器渲染。你需要写一些JavaScript代码来提携。

当在HTML导入文本中运用JavaScript时,有少数要严防的是,HTML导入文本中的document对象实际指的是HTML主文件中的document对象。从前边的代码为例,index.html和
 component.html
的document都是指index.html的document对象。怎么才能采取HTML导入文本中的document
呢?借助link中的import 属性。

index.html

XHTML

var link = document.querySelector(‘link[rel=”import”]’);
link.addEventListener(‘load’, function(e) { var importedDoc =
link.import; // importedDoc points to the document under component.html
});

1
2
3
4
5
var link = document.querySelector(‘link[rel="import"]’);
link.addEventListener(‘load’, function(e) {
  var importedDoc = link.import;
  // importedDoc points to the document under component.html
});

为了赢得component.html中的document 对象,要选用document.currentScript.ownerDocument.

component.html

XHTML

var mainDoc = document.currentScript.ownerDocument; // mainDoc points to
the document under component.html

1
2
var mainDoc = document.currentScript.ownerDocument;
// mainDoc points to the document under component.html

如果您在用webcomponents.js,那么就用document._currentScript来取代document.currentScript。下划线用于填充currentScript属性,因为并不是所有的浏览器都支持那些特性。

component.html

XHTML

var mainDoc = document._currentScript.ownerDocument; // mainDoc points
to the document under component.html

1
2
var mainDoc = document._currentScript.ownerDocument;
// mainDoc points to the document under component.html

经过在本子开始添加下边的代码,你就能够轻松地走访component.html中的document对象,而不用管浏览器是还是不是帮助HTML导入。

XHTML

document._currentScript = document._currentScript ||
document.currentScript;

1
document._currentScript = document._currentScript || document.currentScript;

伸张原有元素

实质上,假诺大家要求一个按钮,完全不要求重新自定义一个要素,Web Components
标准提供了一种扩呈现有标签的点子,把上面的代码调整一下:

JavaScript

document.registerElement(‘button-hello’, { prototype:
Object.create(HTMLButtonElement.prototype, { createdCallback: { value:
function createdCallback() { this.addEventListener(‘click’, () => {
alert(‘hello world’) }) } } }), extends: ‘button’ })

1
2
3
4
5
6
7
8
9
10
11
12
document.registerElement(‘button-hello’, {
  prototype: Object.create(HTMLButtonElement.prototype, {
    createdCallback: {
      value: function createdCallback() {
        this.addEventListener(‘click’, () => {
          alert(‘hello world’)
        })
      }
    }
  }),
  extends: ‘button’
})

然后在 HTML 中要这样使用:

XHTML

<button is=”button-hello”>hello world</button>

1
<button is="button-hello">hello world</button>

使用 is
属性来声称一个增添的类型,看起来也蛮酷的。生命周期和自定义元素标签的保持一致。

当大家须求多个标签组合成新的元素时,大家可以行使自定义的因素标签,可是一旦只是内需在原始的
HTML 标签上拓展增添的话,使用 is 的那种元素扩大的格局就好。

原有的 createElementcreateElementNS,在 Web Components
标准中也壮大成为帮衬元素增加,例如要创立一个 button-hello

JavaScript

const hello = document.createElement(‘button’, ‘button-hello’)

1
const hello = document.createElement(‘button’, ‘button-hello’)

标准文档中还有不少细节上的情节,例如接口的参数表达和要求,回调队列的落到实处须要等,那几个越来越多是对于落成那一个标准的浏览器开发者的渴求,那里不做详细描述了,内容很多,有趣味的自发性查阅:Cutsom
Elements
2016.02.26。

<!DOCTYPE html>
<html>
<head>
<meta charset=”utf-8″ />
<title>outerHTML</title>
</head>
<body>
<div id=”content” class=”test”>
<p>This is <strong>paragraph</strong> with a list
following it</p>
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
</ul>
</div>
<script>
if(typeof HTMLElement !== “undefined” && !(“outerHTML” in
HTMLElement.prototype)) {
console.log(“defined outerHTML”);
HTMLElement.prototype.__defineSetter__(“outerHTML”,function(str){
var fragment = document.createDocumentFragment();
var div = document.createElement(“div”);
div.innerHTML = str;
for(var i=0, n = div.childNodes.length; i<n; i++){
fragment.appendChild(div.childNodes[i]);
}
this.parentNode.replaceChild(fragment, this);
});
//
HTMLElement.prototype.__defineGetter__(“outerHTML”,function(){
var tag = this.tagName;
var attributes = this.attributes;
var attr = [];
//for(var name in attributes){//遍历原型链上成员
for(var i=0,n = attributes.length; i<n; i++){//n指定的特性个数
if(attributes[i].specified){
attr.push(attributes[i].name + ‘=”‘ + attributes[i].value + ‘”‘);
}
}
return ((!!this.innerHTML) ?
‘<‘ + tag + ‘ ‘ + attr.join(‘
‘)+’>’+this.innerHTML+'</’+tag+’>’ :
‘<‘ + tag + ‘ ‘ +attr.join(‘ ‘)+’/>’);
});
}
var content = document.getElementById(“content”);
alert(content.outerHTML)
</script>
</body>
</html>

属性方面的考虑

利用HTML
导入的一个利益是力所能及将资源集团起来,可是也代表在加载那些资源的时候,由于使用了部分格外的HTML文件而让尾部变得过大。有几点是索要考虑的:

和新星版的分歧

面前我提到说文档的更新变更很快,截至至自己写这些稿子的时候,最新的文档是以此:Custom
Elements 2016.07.21。

细节不做描述了,讲讲我见状的最大变迁,就是向 ES6 靠拢。大致有下边三点:

  • 从原来的壮大 prototype 来定义元素调整为提出采取 class extends 的方法
  • 注册自定义元素接口调整,越发方便使用,传入 type 和 class 即可
  • 生命周期回调调整,createdCallback 直接用 class 的 constructor

前七个点,我们平昔看下代码,原本的代码根据新的正规化,应该调整为:

JavaScript

class ButtonHelloElement extends HTMLButtonElement { constructor() {
super() this.addEventListener(‘click’, () => { alert(‘hello world’)
}) } } customElements.define(‘button-hello’, ButtonHelloElement, {
extends: ‘button’ })

1
2
3
4
5
6
7
8
9
10
11
class ButtonHelloElement extends HTMLButtonElement {
  constructor() {
    super()
 
    this.addEventListener(‘click’, () => {
      alert(‘hello world’)
    })
  }
}
 
customElements.define(‘button-hello’, ButtonHelloElement, { extends: ‘button’ })

从代码上看会倍感越是
OO,编写上也比原来要显得方便一些,原本的生命周期回调是调整为新的:

  • constructor in class 成效相当于原来的 createdCallback
  • connectedCallback 功能相当于 attachedCallback
  • disconnectedCallback 作用约等于 detachedCallback
  • adoptedCallback 使用 document.adoptNode(node) 时触发
  • attributeChangedCallback 和原先保持一致

connect 事件和插入元素到 document 有稍许区分,主要就是插入元素到
document 时,元素状态会变成 connected,这时会触发
connectedCallback,disconnect 亦是那样。

只要要取得 <p id=”outerID”>sdfdsdfsd</p> 的 P的outerHTML
代码:

剖析依赖

倘诺HTML主文件要看重五个导入文本,而且导入文本中富含相同的库,那时会怎么着呢?例如,你要从导入文本中加载jQuery,如果每个导入文本都含有加载jQuery的script标签,那么jQuery就会被加载一次,并且也会被执行四回。

index.html

XHTML

<link rel=”import” href=”component1.html”> <link rel=”import”
href=”component2.html”>

1
2
<link rel="import" href="component1.html">
<link rel="import" href="component2.html">

component1.html

XHTML

<script src=”js/jquery.js”></script>

1
<script src="js/jquery.js"></script>

component2.html

XHTML

<script src=”js/jquery.js”></script>

1
<script src="js/jquery.js"></script>

HTML导入自动帮您解决了这些题材。

与加载一遍script标签的做法各异,HTML
导入对已经加载过的HTML文件不再进行加载和实践。在此此前边的代码为例,通过将加载jQuery的script标签打包成一个HTML导入文本,那样jQuery就只被加载和推行三遍了。

但那还有一个标题:大家增添了一个要加载的公文。怎么处理数据膨胀的公文呢?幸运的是,大家有一个叫vulcanize的工具来化解那么些标题。

HTML Imports

复制代码 代码如下:

统一网络请求

Vulcanize 能将多少个HTML文件合并成一个文本,从而收缩了互联网连接数。你可以信赖npm安装它,并且用命令行来行使它。你可能也在用 grunt和gulp 托管有些职分,那样的话你可以把vulcanize作为创设进程的一局地。

为明白析看重以及联合index.html中的导入文本,使用如下命令:

JavaScript

$ vulcanize -o vulcanized.html index.html

1
$ vulcanize -o vulcanized.html index.html

经过执行这一个命令,index.html中的看重会被分析,并且会爆发一个统一的HTML文件,称作 vulcanized.html。学习越多关于vulcanize的知识,请看这儿。

专注:http2的服务器推送功能被考虑用于未来消除文件的衔接与统一。

概述

HTML Imports 是一种在 HTMLs 中援引以及复用其余的 HTML 文档的法门。这几个Import 很雅观,能够概括明了为大家普遍的沙盘中的include 之类的效率。

俺们最普遍的引入一个 css 文件的方法是:

XHTML

澳门葡京,<link rel=”stylesheet” href=”/css/master.css”>

1
<link rel="stylesheet" href="/css/master.css">

Web Components 现在提供多了一个以此:

XHTML

<link rel=”import” href=”/components/header.html”>

1
<link rel="import" href="/components/header.html">

var _p = document.getElementById(‘outerID’);
_P = _P.cloneNode();
var _DIV = document.createElement();
_DIV.appendChild(_P);
alert(_DIV.innerHTML); 就是P的outerHTML;

把Template、Shadow DOM、自定义元素跟HTML导入结合起来

让大家对这么些小说连串的代码应用HTML导入。你前边恐怕没有看过这几个小说,我先解释一下:Template可以让你用注解的点子定义你的自定义元素的始末。Shadow
DOM可以让一个因素的style、ID、class只效劳到其本身。自定义元素得以让您自定义HTML标签。通过把这个跟HTML导入结合起来,你自定义的web
组件会变得模块化,具有复用性。任何人添加一个Link标签就足以采取它。

x-component.html

XHTML

<template id=”template”> <style> … </style> <div
id=”container”> <img
src=”; <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.importNode(template.content, true); root.appendChild(clone); }
} }) }); </script>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<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.importNode(template.content, true);
          root.appendChild(clone);
        }
      }
    })
  });
</script>

index.html

XHTML

… <link rel=”import” href=”x-component.html”> </head>
<body> <x-component> <h1>This is Custom
Element</h1> </x-component> …

1
2
3
4
5
6
7
8
  <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的平等,你没必要再写一些老大难的代码,它会自动为你注册。

HTMLLinkElement

原本的 link 标签在添加了 HTML Import 之后,多了一个只读的 import
属性,当出现上面三种情形时,那个特性为 null

  • link 不是用来 import 一个 HTML 的。
  • link 元素不在 document 中。

不然,这几个特性会回到一个象征引入的 HTML 文件的文档对象,类似于
document。比如说,在上头的代码基础上,可以这样做:

JavaScript

const link = document.querySelector(‘link[rel=import]’) const header =
link.import; const pulse = header.querySelector(‘div.logo’);

1
2
3
4
const link = document.querySelector(‘link[rel=import]’)
const header = link.import;
 
const pulse = header.querySelector(‘div.logo’);

firefox没有outerHTML用以下办法解决

支撑的浏览器

Chrome 和
Opera提供对HTML导入的支撑,Firefox要在二〇一四年1二月后才支撑(Mozilla表示Firefox不安顿在近期提供对HTML导入的支撑,声称须求首先驾驭ES6的模块是如何完毕的)。

你可以去chromestatus.com或caniuse.com查询浏览器是不是援救HTML导入。想要在其他浏览器上选用HTML导入,可以用webcomponents.js(原名platform.js)。

阻塞式

俺们要明了的是,默许的 link 加载是阻塞式的,除非你给她添加一个 async
标识。

阻塞式从某种程度上讲是有需求的,当你 improt
的是一个一体化的自定义组件并且须要在主 HTML
中用竹签间接采取时,非阻塞的就会油然则生谬误了,因为标签还未曾被登记。

复制代码 代码如下:

有关资源

HTML导入就介绍这么多了。如若你想学越来越多关于HTML导入的学问,请前往:

  • HTML Imports: #include for the web –
    HTML5Rocks
  • HTML Imports
    spec

    赞 1 收藏
    评论

document

有一些值得注意的是,在 import 的 HTML 中,咱们编辑的 script 里边的
document 是指向 import 这个 HTML 的主 HTML 的 document。

假定大家要拿走 import 的 HTML 的 document 的话,得那样来:

JavaScript

const d = document.currentScript.ownerDocument

1
const d = document.currentScript.ownerDocument

如此设计是因为 import 进来的 HTML 需求用到主 HTML 的
document。例如我们下边提到的 registerElement

在一个被 import 的 HTML 文件中选择上边多个方法会抛出一个
InvalidStateError
异常:

  • document.open()
  • document.write()
  • document.close()

对此 HTML
Import,标准文档中还有很大一些情节是关于多少个依靠加载的拍卖算法的,在此处就不详述了,有机会的话找时间再开篇谈,那个内容是索要浏览器去完结的。

/**
* 包容firefox的 outerHTML
使用以下代码后,firefox可以利用element.outerHTML
**/
if(window.HTMLElement) {
HTMLElement.prototype.__defineSetter__(“outerHTML”,function(sHTML){
var r=this.ownerDocument.createRange();
r.setStartBefore(this);
var df=r.createContextualFragment(sHTML);
this.parentNode.replaceChild(df,this);
return sHTML;
});
HTMLElement.prototype.__defineGetter__(“outerHTML”,function(){
var attr;
var attrs=this.attributes;
var str=”<“+this.tagName.toLowerCase();
for(var i=0;i<attrs.length;i++){
attr=attrs[i];
if(attr.specified)
str+=” “+attr.name+’=”‘+attr.value+'”‘;
}
if(!this.canHaveChildren)
return str+”>”;
return
str+”>”+this.innerHTML+”</”+this.tagName.toLowerCase()+”>”;
});
HTMLElement.prototype.__defineGetter__(“canHaveChildren”,function(){
switch(this.tagName.toLowerCase()){
case “area”:
case “base”:
case “basefont”:
case “col”:
case “frame”:
case “hr”:
case “img”:
case “br”:
case “input”:
case “isindex”:
case “link”:
case “meta”:
case “param”:
return false;
}
return true;
});
}

至于作者:XfLoops

澳门葡京 9

乐乎新浪:@XfLoops
个人主页 ·
我的小说 ·
10

澳门葡京 10

HTML Templates

测试有效.
至于insertAdjacentHTML包容的解新决办法

概述

其一东西很粗略,用过 handlebars 的人都清楚有这么一个事物:

XHTML

<script id=”template” type=”text/x-handlebars-template”> …
</script>

1
2
3
<script id="template" type="text/x-handlebars-template">
  …
</script>

任何模板引擎也有像样的东西,那么 HTML Templates
便是把那个事物官方口径,提供了一个 template
标签来存放将来须求不过暂时不渲染的 HTML 代码。

将来可以这么写了:

XHTML

<template id=”template”> … </template>

1
2
3
<template id="template">
  …
</template>

复制代码 代码如下:

接口和选拔

template 元素有一个只读的属性 content,用于再次来到那几个 template
里边的始末,重返的结果是一个 DocumentFragment

实际是何许使用的,直接参考官方给出的例证:

XHTML

<!doctype html> <html lang=”en”> <head>
<title>Homework</title> <body> <template
id=”template”><p>Smile!</p></template>
<script> let num = 3; const fragment =
document.getElementById(‘template’).content.cloneNode(true); while
(num– > 1) {
fragment.firstChild.before(fragment.firstChild.cloneNode(true));
fragment.firstChild.textContent += fragment.lastChild.textContent; }
document.body.appendChild(fragment); </script> </html>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<!doctype html>
<html lang="en">
  <head>
    <title>Homework</title>
  <body>
    <template id="template"><p>Smile!</p></template>
    <script>
      let num = 3;
      const fragment = document.getElementById(‘template’).content.cloneNode(true);
      while (num– > 1) {
        fragment.firstChild.before(fragment.firstChild.cloneNode(true));
        fragment.firstChild.textContent += fragment.lastChild.textContent;
      }
      document.body.appendChild(fragment);
    </script>
</html>

使用 DocumentFragment 的 clone 方法以 template
里的代码为底蕴创设一个因素节点,然后你便可以操作那几个元素节点,最后在急需的时候插入到
document 中一定岗位便足以了。

Template 相关的东西不多,而且它现在曾经是纳入生效的
正式文档
中了。

咱俩接下去看看重磅的 Shadow DOM。

//—在组件最后插入html代码
function InsertHtm(op,code,isStart){
if(Dvbbs_IsIE5)
op.insertAdjacentHTML(isStart ? “afterbegin” : “afterEnd”,code);
else{
var range=op.ownerDocument.createRange();
range.setStartBefore(op);
var fragment = range.createContextualFragment(code);
if(isStart)
op.insertBefore(fragment,op.firstChild);
else
op.appendChild(fragment);
}
}

Shadow DOM

有关inner/outerHTML在NC6中的参考
DOM level 1 has no methods to allow for insertion of unparsed HTML into
the document tree (as IE allows with insertAdjacentHTML or assignment to
inner/outerHTML).NN6 (currently in beta as NN6PR3) know supports the
.innerHTMLproperty of HTMLElements so that you can read or write the
innerHTML of a page element like in IE4+.NN6 also provides a DOM level 2
compliant Range object to which a createContextualFragment(‘html source
string’)was added to spare DOM scripters the task of parsing html and
creating DOM elements.You create a Range with var range =
document.createRange();Then you should set its start point to the
element where you want to insert the html for instance var someElement =
document.getElementById(‘elementID’);
range.setStartAfter(someElement);Then you create a document fragment
from the html source to insert for example var docFrag =
range.createContextualFragment(‘<P>Kibology for
all.</P>’);and insert it with DOM methods
someElement.appendChild(docFrag);The Netscape JavaScript 1.5 version
even provides so called setters for properties which together with the
ability to prototype the DOM elements allows to emulate setting of
outerHMTL for NN6:<SCRIPT LANGUAGE=”JavaScript1.5″>if
(navigator.appName == ‘Netscape’) { HTMLElement.prototype.outerHTML
setter = function (html) { this.outerHTMLInput = html; var range =
this.ownerDocument.createRange(); range.setStartBefore(this); var
docFrag = range.createContextualFragment(html);
this.parentNode.replaceChild(docFrag, this); }}</SCRIPT> If you
insert that script block you can then write cross browser code assigning
to .innerHTML .outerHTMLfor instance document.body.innerHTML =
‘<P>Scriptology for all</P>’;which works with both IE4/5 and
NN6.The following provides getter functions for .outerHTMLto allow to
read those properties in NN6 in a IE4/5 compatible way. Note that while
the scheme of traversing the document tree should point you in the right
direction the code example might not satisfy your needs as there are
subtle difficulties when trying to reproduce the html source from the
document tree. See for yourself whether you like the result and improve
it as needed to cover other exceptions than those handled (for the empty
elements and the textarea
element).<HTML><HEAD><STYLE></STYLE><SCRIPT
LANGUAGE=”JavaScript1.5″>var emptyElements = { HR: true, BR: true,
IMG: true, INPUT: true};var specialElements = { TEXTAREA:
true};HTMLElement.prototype.outerHTML getter = function () { return
getOuterHTML (this);}function getOuterHTML (node) { var html = ”;
switch (node.nodeType) { case Node.ELEMENT_NODE: html += ‘<‘; html
+= node.nodeName; if (!specialElements[node.nodeName]) { for (var a =
0; a < node.attributes.length; a++) html += ‘ ‘ +
node.attributes[a].nodeName.toUpperCase() + ‘=”‘ +
node.attributes[a].nodeValue + ‘”‘; html += ‘>’; if
(!emptyElements[node.nodeName]) { html += node.innerHTML; html +=
‘<\/’ + node.nodeName + ‘>’; } } else switch (node.nodeName) {
case ‘TEXTAREA’: for (var a = 0; a < node.attributes.length; a++) if
(node.attributes[a].nodeName.toLowerCase() != ‘value’) html += ‘ ‘ +
node.attributes[a].nodeName.toUpperCase() + ‘=”‘ +
node.attributes[a].nodeValue + ‘”‘; else var content =
node.attributes[a].nodeValue; html += ‘>’; html += content; html +=
‘<\/’ + node.nodeName + ‘>’; break; } break; case
Node.TEXT_NODE: html += node.nodeValue; break; case Node.COMMENT_NODE:
html += ‘<!’ + ‘–‘ + node.nodeValue + ‘–‘ + ‘>’; break; } return
html;}</SCRIPT></HEAD><BODY><A HREF=”javascript:
alert(document.documentElement.outerHTML); void 0″>show
document.documentElement.outerHTML</A>|<A HREF=”javascript:
alert(document.body.outerHTML); void 0″>show
document.body.outerHTML</A>|<A HREF=”javascript:
alert(document.documentElement.innerHTML); void 0″>show
document.documentElement.innerHTML</A>|<A HREF=”javascript:
alert(document.body.innerHTML); void 0″>show
document.body.innerHTML</A><FORM
NAME=”formName”><TEXTAREA NAME=”aTextArea” ROWS=”5″
COLS=”20″>JavaScript.FAQTs.comKibology for
all.</TEXTAREA></FORM><DIV><P>JavaScript.FAQTs.com</P><BLOCKQUOTE>Kibology
for all.<BR>All for
Kibology.</BLOCKQUOTE></DIV></BODY></HTML>Note
that the getter/setter feature is experimental and its syntax is subject
to change.
HTMLElement.prototype.innerHTML setter = function (str) { var r =
this.ownerDocument.createRange(); r.selectNodeContents(this);
r.deleteContents(); var df = r.createContextualFragment(str);
this.appendChild(df); return str;}HTMLElement.prototype.outerHTML setter
= function (str) { var r = this.ownerDocument.createRange();
r.setStartBefore(this); var df = r.createContextualFragment(str);
this.parentNode.replaceChild(df, this); return str;}
HTMLElement.prototype.innerHTML getter = function () { return
getInnerHTML(this);}
function getInnerHTML(node) { var str = “”; for (var i=0;
i<node.childNodes.length; i++) str +=
getOuterHTML(node.childNodes.item(i)); return str;}
HTMLElement.prototype.outerHTML getter = function () { return
getOuterHTML(this)}
function getOuterHTML(node) { var str = “”; switch (node.nodeType) {
case 1: // ELEMENT_NODE str += “<” + node.nodeName; for (var i=0;
i<node.attributes.length; i++) { if
(node.attributes.item(i).nodeValue != null) { str += ” ” str +=
node.attributes.item(i).nodeName; str += “=\””; str +=
node.attributes.item(i).nodeValue; str += “\””; } }
if (node.childNodes.length == 0 && leafElems[node.nodeName]) str +=
“>”; else { str += “>”; str += getInnerHTML(node); str += “<” +
node.nodeName + “>” } break; case 3: //TEXT_NODE str +=
node.nodeValue; break; case 4: // CDATA_SECTION_NODE str +=
“<![CDATA[” + node.nodeValue + “]]>”; break; case 5: //
ENTITY_REFERENCE_NODE str += “&” + node.nodeName + “;” break;
case 8: // COMMENT_NODE str += “<!–” + node.nodeValue + “–>”
break; }
return str;}
var _leafElems = [“IMG”, “HR”, “BR”, “INPUT”];var leafElems = {};for
(var i=0; i<_leafElems.length; i++) leafElems[_leafElems[i]] =
true;
下一场大家得以封成JS引用
if (/Mozilla\/5\.0/.test(navigator.userAgent))
document.write(‘<script type=”text/javascript”
src=”mozInnerHTML.js”></sc’ + ‘ript>’);

概述

Shadow DOM
好像提议好久了,最实质的必要是内需一个隔断组件代码效能域的事物,例如我组件代码的
CSS 无法影响其余零件之类的,而 iframe 又太重并且可能有各样奇怪难题。

可以那样说,Shadow DOM
目的在于提供一种更好地社团页面元素的方法,来为日益复杂的页面使用提供强有力支撑,幸免代码间的互相影响。

看下在 chrome 它会是什么的:

澳门葡京 11

大家可以通过 createShadowRoot() 来给一个因素节点创立 Shadow
Root,那些要素类型必须是底下列表的其中一个,否则会抛出 NotSupportedError
至极。

  • 自定义的要素
  • article
  • aside
  • blockquote
  • body
  • div
  • header, footer
  • h1, h2, h3, h4, h5, h6
  • nav
  • p
  • section
  • span

createShadowRoot() 是现在 chrome 落成的
API,来自文档:https://www.w3.org/TR/2014/WD…。最新的文档
API 已经调整为 attachShadow()

归来的 Shadow Root 对象从 DocumentFragment
继承而来,所以可以行使相关的一对方法,例如shadowRoot.getElementById('id')
来获取 Shadow DOM 里边的元素。

简易的利用如下:

JavaScript

const div = document.getElementById(‘id’) const shadowRoot =
div.createShadowRoot() const span = document.createElement(‘span’)
span.textContent = ‘hello world’ shadowRoot.appendChild(span)

1
2
3
4
5
6
const div = document.getElementById(‘id’)
const shadowRoot = div.createShadowRoot()
const span = document.createElement(‘span’)
 
span.textContent = ‘hello world’
shadowRoot.appendChild(span)

在此处,我把那个 div 成为是其一 Shadow DOM 的
宿主元素,上边的情节会继续使用那一个名叫。

Shadow DOM 本身就为了代码隔离而生,所以在 document 上运用 query
时,是没办法获取到 Shadow DOM 里边的因素的,须要在 Shadow Root 上做 query
才行。

在此地附上一个文档,里边有详尽的关于新的科班和后日 blink 引擎落成的
Shadow DOM 的界别,官方上称为 v0 和 v1:Shadow DOM v1 in
Blink。

复制代码 代码如下:

API

Shadow Root 除了从 DocumentFragment
继承而来的性质和措施外,还多了其它三个特性:

  • host 只读属性,用来收获那些 Shadow Root 所属的要素
  • innerHTML 用来获得或者设置里边的 HTML 字符串,和大家常用的
    element.innerHTML 是同等的

除此以外,在新型的规范文档中,元素除了下边提到的 attachShadow
方法之外,还多了五个特性:

  • assignedSlot 只读,那几个元素即便被分配到了某个 Shadow DOM 里边的
    slot,那么会重临这些相应的 slot 元素
  • slot 元素的 slot 属性,用来指定 slot 的名号
  • shadowRoot 只读,元素上面对应的 Shadow Root 对象

slot 是何许?接着看上边的始末,看完下一节的末段一部分就会分晓上述情节和
slot 相关的七个 API 有怎么着效益。

<script language=”JavaScript” type=”Text/JavaScript”>
<!–
var emptyElements = { HR: true, BR: true, IMG: true, INPUT: true }; var
specialElements = { TEXTAREA: true };
HTMLElement.prototype.outerHTML getter = function() {
return getOuterHTML(this);
}
function getOuterHTML(node) {
var html = ”;
switch (node.nodeType) {
case Node.ELEMENT_NODE: html += ‘<‘; html += node.nodeName; if
(!specialElements[node.nodeName]) {
for (var a = 0; a < node.attributes.length; a++)
html += ‘ ‘ + node.attributes[a].nodeName.toUpperCase() + ‘=”‘ +
node.attributes[a].nodeValue + ‘”‘;
html += ‘>’;
if (!emptyElements[node.nodeName]) {
html += node.innerHTML;
html += ‘<\/’ + node.nodeName + ‘>’;
}
} else
switch (node.nodeName) {
case ‘TEXTAREA’: for (var a = 0; a < node.attributes.length; a++)
if (node.attributes[a].nodeName.toLowerCase() != ‘value’)
html
+= ‘ ‘ + node.attributes[a].nodeName.toUpperCase() + ‘=”‘ +
node.attributes[a].nodeValue

slot

slot
提供了在运用自定义标签的时候可以传递子模板给到里面选择的力量,可以省略看下
Vue 的一个例证。

俺们先来看下现在 chrome 可以跑的 v0 版本,这一个本子是提供了一个 content
标签,代表了一个占位符,并且有一个 select 属性用来指定使用什么子元素。

XHTML

<!– component input-toggle template –> <input
type=”checkbox”></input> <content
select=”.span”></content>

1
2
3
<!– component input-toggle template –>
<input type="checkbox"></input>
<content select=".span"></content>

自定义的因素里边的子元素代码是这么的:

XHTML

<input-toggle name=”hello”> <span>hello</span>
<span class=”span”>test</span> </input-toggle>

1
2
3
4
<input-toggle name="hello">
  <span>hello</span>
  <span class="span">test</span>
</input-toggle>

这就是说显示的结果会和下边的代码是相同的:

XHTML

<input-toggle name=”hello”> <input
type=”checkbox”></input> <span
class=”span”>test</span> </input-toggle>

1
2
3
4
<input-toggle name="hello">
  <input type="checkbox"></input>
  <span class="span">test</span>
</input-toggle>

此间只是说显示结果,实际上,input-toggle 里边应该是开创了一个 Shadow
DOM,然后 content 标签引用了目标的 span 内容,在 chrome 看是这么的:

澳门葡京 12

接下来,是流行专业中的 slot 使用格局,直接上例子代码:

XHTML

<!– component input-toggle template –> <input
type=”checkbox”></input> <slot name=”text”></slot>

1
2
3
<!– component input-toggle template –>
<input type="checkbox"></input>
<slot name="text"></slot>

在自定义的元素标签是如此使用 slot 的:

XHTML

<input-toggle name=”hello”> <input
type=”checkbox”></input> <span class=”span”
slot=”text”>test</span> </input-toggle>

1
2
3
4
<input-toggle name="hello">
  <input type="checkbox"></input>
  <span class="span" slot="text">test</span>
</input-toggle>

通过 slot="text" 的质量来让要素内部的 slot
占位符可以引用到这些因素,三个元素选取这几个特性也是足以的。那样子大家便具有了采纳标签是从外部传
template 给到自定义元素的内部去行使,而且装有指定放在这里的能力。

  • ‘”‘;
    else
    var content = node.attributes[a].nodeValue;
    html += ‘>’; html += content; html += ‘<\/’ + node.nodeName +
    ‘>’; break;
    } break;
    case Node.TEXT_NODE: html += node.nodeValue; break;
    case Node.COMMENT_NODE: html += ‘<!’ + ‘–‘ + node.nodeValue + ‘–‘
  • ‘>’; break;
    }
    return html;
    }
    //–>
    </script>

CSS 相关

因为有 Shadow DOM 的留存,所以在 CSS
上又添加了成百上千连锁的事物,其中有些或者属于研讨中的草案,命名之类的或许会有转移,上边提及的始末根本来源于文档:Shadow
DOM in CSS scoping
1,很多有些在 chrome
是已经达成的了,有趣味可以写 demo 试试。

因为 Shadow DOM
很大程度上是为着隔离样式效用域而诞生的,主文档中的体制规则不对 Shadow
DOM 里的子文档生效,子文档中的体裁规则也不影响外部文档。

但不可防止的,在好几场景下,我们必要外部可以决定 Shadow DOM
中样式,如提供一个组件给你,有时候你会愿意得以自定义它其中的有的体裁,同时,Shadow
DOM
中的代码有时候可能必要可以决定其所属元素的体制,甚至,组件内部可以定义上面提到的经过
slot 传递进入的 HTML 的样式。所以啊,是的,CSS
选取器中添加了几个伪类,我们逐一来看下它们有怎样成效。

在读书下边描述的时候,请留心一下选取器的代码是在怎么职位的,Shadow DOM
内部如故外部。

:host 用于在 Shadow DOM 内部甄选到其宿主元素,当它不是在 Shadow DOM
中使用时,便匹配不到任意元素。

在 Shadow DOM 中的 * 选取器是不能选用到其宿主元素的。

:host( <selector> )
括号中是一个选取器,那一个可以明白为是一个用来包容在主文档和 Shadow DOM
中使用的办法,当这些选取器在 Shadow DOM
中时,会合营到括号中接纳器对应的宿主元素,如果不是,则匹配括号中选择器可以同盟到的元素。

文档中提供了一个例子:

XHTML

<x-foo class=”foo”> <“shadow tree”> <div
class=”foo”>…</div> </> </x-foo>

1
2
3
4
5
<x-foo class="foo">
  <"shadow tree">
    <div class="foo">…</div>
  </>
</x-foo>

在这个 shadow tree 内部的体裁代码中,会有那般的结果:

  • :host 匹配 <x-foo> 元素
  • x-foo 匹配不到元素
  • .foo 只匹配到 <div> 元素
  • .foo:host 匹配不到元素
  • :host(.foo) 匹配 <x-foo> 元素

:host-context( <selector> ),用于在 Shadow DOM
中来检测宿主元素的父级元素,假诺宿主元素或者其祖先元素可以被括号中的拔取器匹配到的话,那么这么些伪类选拔器便匹配到那么些Shadow DOM
的宿主元素。个人了然是用来在宿主元素外部因素满足一定的原则时累加样式。

::shadow 这一个伪类用于在 Shadow DOM 外部匹配其中间的因素,而 /deep/
那一个标识也有相同的作用,我们来看一个事例:

XHTML

<x-foo> <“shadow tree”> <div> <span
id=”not-top”>…</span> </div> <span
id=”top”>…</span> </> </x-foo>

1
2
3
4
5
6
7
8
<x-foo>
   <"shadow tree">
     <div>
       <span id="not-top">…</span>
     </div>
     <span id="top">…</span>
   </>
</x-foo>

对此上述这一段代码的 HTML 结构,在 Shadow DOM
外部的样式代码中,会是那样的:

  • x-foo::shadow > span 可以匹配到 #top 元素
  • #top 匹配不到元素
  • x-foo /deep/ span 可以匹配到 #not-top#top 元素

/deep/ 那一个标识的效应和大家的 >
接纳器有点类似,只可是它是匹配其对应的 Shadow DOM
内部的,那些标识可能还会扭转,例如改成 >> 或者 >>>
之类的,个人感觉, >> 会更舒适。

最终一个,用于在 Shadow DOM 内部调整 slot
的体制,在我翻看的那些文档中,暂时是以 chrome 达成的为准,使用
::content 伪类,不消除有更新为 ::slot
的可能。我们看一个例证来打探一下,即使名称调整了也是基本上的用法:

XHTML

<x-foo> <div id=”one” class=”foo”>…</div> <div
id=”two”>…</div> <div id=”three” class=”foo”> <div
id=”four”>…</div> </div> <“shadow tree”> <div
id=”five”>…</div> <div id=”six”>…</div>
<content select=”.foo”></content> </”shadow tree”>
</x-foo>

1
2
3
4
5
6
7
8
9
10
11
12
<x-foo>
  <div id="one" class="foo">…</div>
  <div id="two">…</div>
  <div id="three" class="foo">
    <div id="four">…</div>
  </div>
  <"shadow tree">
    <div id="five">…</div>
    <div id="six">…</div>
    <content select=".foo"></content>
  </"shadow tree">
</x-foo>

在 Shadow DOM 内部的体制代码中,::content div 可以合作到
#one#three#four,留意一下 #two
为啥没被匹配到,因为它从未被 content
元素选中,即不会展开引用。要是更换成 slot 的 name 引用的主意亦是同理。

层叠规则,根据那一个文档的布道,对于五个先行级别相同的 CSS 申明,没有带
!important 的,在 Shadow DOM 外部申明的先期级高于在 Shadow DOM
内部的,而带有 !important
的,则相反。个人觉得,那是提需要外部自然的控制能力,同时让里面可以界定一定的震慑范围。

继续方面相对不难,在 Shadow DOM 内部的头号元素样式从宿主元素继承而来。

至今,Web Components
三个部分介绍截至了,其中有一对细节,浏览器完毕细节,还有使用上的有些细节,是不曾提及的,因为详细笔录以来,还会有广大东西,内容很多。当使用进度中有疑难时能够重新翻开标准文档,有机遇的话会再完善这一个文章。下一部分会把那三个内容结合起来,全体看下
Web Components 是怎么使用的。

Tree和render
tree的创设,从而进步页面质量。为此大家得以把页面中那几个首屏渲染不可知的部…

Web Components

Web Components 总的来说是提供一整套到家的卷入机制来把 Web
组件化那个事物规范,每个框架已毕的机件都统一标准地开展输入输出,那样可以更好促进组件的复用。结合上面各样部分的内容,我们构成一起来看下应该怎么利用那些标准来贯彻我们的零件:

JavaScript

<!– components/header.html –> <template id=””>
<style> ::content li { display: inline-block; padding: 20px 10px;
} </style> <content select=”ul”></content>
</template> <script> (function() { const element =
Object.create(HTMLInputElement.prototype) const template =
document.currentScript.ownerDocument.querySelector(‘template’)
element.createdCallback = function() { const shadowRoot =
this.createShadowRoot() const clone =
document.importNode(template.content, true)
shadowRoot.appendChild(clone) this.addEventListener(‘click’,
function(event) { console.log(event.target.textContent) }) }
document.registerElement(‘test-header’, { prototype: element }) })()
</script>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<!– components/header.html –>
<template id="">
<style>
::content li {
  display: inline-block;
  padding: 20px 10px;
}
</style>
<content select="ul"></content>
</template>
<script>
(function() {
  const element = Object.create(HTMLInputElement.prototype)
  const template = document.currentScript.ownerDocument.querySelector(‘template’)
 
  element.createdCallback = function() {
    const shadowRoot = this.createShadowRoot()
    const clone = document.importNode(template.content, true)
    shadowRoot.appendChild(clone)
 
    this.addEventListener(‘click’, function(event) {
      console.log(event.target.textContent)
    })
  }
 
  document.registerElement(‘test-header’, { prototype: element })
})()
</script>

那是一个概括的机件的例证,用于定义一个
test-header,并且给传递进入的子元素 li
添加了有些组件内部的体制,同时给组件绑定了一个点击事件,来打印点击目的的公文内容。

看下怎么样在一个 HTML 文件中引入并且使用一个组件:

XHTML

<!– index.html –> <!DOCTYPE html> <html>
<head> <meta charset=”utf-8″> <title></title>
<link rel=”import” href=”components/header.html”> </head>
<body> <test-header> <ul> <li>Home</li>
<li>About</li> </ul> </test-header>
</body> </html>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<!– index.html –>
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title></title>
 
    <link rel="import" href="components/header.html">
  </head>
  <body>
    <test-header>
      <ul>
        <li>Home</li>
        <li>About</li>
      </ul>
    </test-header>
  </body>
</html>

一个 import<link> 把组件的 HTML
文件引用进来,那样会执行组件中的脚本,来注册一个 test-header
元素,那样子我们便得以在主文档中使用那些元素的价签。

上边的事例是可以在 chrome 正常运行的。

故此,依据上边简单的事例可以见见,种种部分的情节是有机构成在一道,Custom
Elements 提供了自定义元素和标签的力量,template 提供组件模板,import
提供了在 HTML 中合理引入组件的艺术,而 Shadow DOM
则处理组件间代码隔离的难点。

只得认可,Web Components
标准的提议解决了有的难点,必须交由浏览器去处理的是 Shadow DOM,在并未
Shadow DOM
的浏览器上贯彻代码隔离的章程多多少少有弱点。个人我觉着组件化的逐一 API
不够简洁易用,如故有 getElementById
这么些的寓意,不过交由逐一类库去简化也得以承受,而 import
成效上没难题,不过加载三个零件时质量难点要么值得说道,标准或许必要在这些下面提供更加多给浏览器的引导,例如是或不是有可能提供一种单一请求加载七个零件
HTML 的不二法门等。

在现今的移动化趋势中,Web Components 不仅仅是 Web
端的题材,更加多的开发者期望以 Web
的法门去贯彻移动接纳,而多端复用的兑现渐渐是以组件的花样铺开,例如
React Native 和
Weex。所以 Web Components
的正式可能会影响到多端开发 Web 化的一个情势和前进。

最终,再啰嗦一句,Web Components
个人觉得依然鹏程发展趋势,所以才有了这么些文章。

1 赞 4 收藏
评论

澳门葡京 13

相关文章

发表评论

电子邮件地址不会被公开。 必填项已用*标注

*
*
Website