>

是个什么样的东西,自定义元素教程

- 编辑:至尊游戏网站 -

是个什么样的东西,自定义元素教程

HTML 自定义成分教程

2017/06/22 · HTML5 · 自定义成分

最早的作品出处: 阮一峰   

零件是 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 则是与世隔阂组件间代码的冲突和震慑。

上面分别是每一片段的笔记内容。

二、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

三、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 来做尝试,最后笔者会再轻易写一下风尚文书档案和那个的差异。

四、参谋链接

  • 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 说它和谐主要不是做这些事情的。

生命周期和回调

在这里个 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>

恢宏原有成分

实质上,假设大家供给三个开关,完全没有要求重新自定义多个成分,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。

和新星版的分化

前边笔者关系说文书档案的翻新更动相当的慢,停止至自家写那么些小说的时候,最新的文档是那些: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 亦是这么。

HTML Imports

概述

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">

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');

阻塞式

大家要通晓的是,暗许的 link 加载是阻塞式的,除非你给她加多二个 async 标识。

阻塞式从某种程度上讲是有供给的,当您 improt 的是贰个安然无恙的自定义组件而且须求在主 HTML 中用竹签直接行使时,非阻塞的就能够冒出谬误了,因为标签还还未有被登记。

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,规范文书档案中还会有异常的大意气风发部分剧情是有关多少个依靠加载的管理算法的,在此地就不详述了,有机缘的话找时间再开篇谈,这么些剧情是急需浏览器去贯彻的。

HTML Templates

概述

其一事物很简单,用过 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。

Shadow DOM

概述

Shadow DOM 好像建议好久了,最本色的供给是亟需三个切断组件代码效用域的东西,比如小编组件代码的 CSS 不能够影响别的零件之类的,而 iframe 又太重何况可能有种种奇异难题。

能够那样说,Shadow DOM 意在提供后生可畏种越来越好地公司页面成分的方法,来为稳步复杂的页面使用提供有力支撑,制止代码间的互相影响。

看下在 chrome 它会是何等的:

图片 9

大家能够通过 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 有何效率。

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 看是那般的:

图片 10

然后,是风靡正规中的 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 给到自定义成分的个中去行使,何况富有钦命放在那的本领。

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 是怎么接受的。

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 收藏 评论

图片 11

本文由软件综合发布,转载请注明来源:是个什么样的东西,自定义元素教程