Web Components是不是Web的未来

今天 ,Web 组件已经从本质上改变了HTML。初次接触时,它看起来像一个全新的技术。Web组件最初的目的是使开发人员拥有扩展浏览器标签的能力,可以自由的进行定制组件。面对新的技术,你可能会觉得无从下手。那这篇文章将为你揭开Web组件神秘的面纱。如果你已经熟知HTML标签和DOM编程,已经拥有了大量可用的Web组件,那么你已经是Web组件专家了。

Web组件的现状

随着各式各样的用户需求,浏览器的原生组件已经无法满足需求。Web组件也就变得越来越重要。

我们将以自定义一个传统三方插件为例来介绍Web组件。

首先,需要引用插件的CSS和JavaScript资源:

<link rel="stylesheet" type="text/css" href="my-widget.css" />

<script src="my-widget.js"></script>

接下来,我们需要向页面中添加占位符。

<div data-my-widget></div>

最后,我们需要使用脚本来找到并且实例化这个占位符为Web组件。

// 使用 jQuery 初始化组件

$(function() {

$('[data-my-widget]').myWidget();

});

通过以上是三个基本步骤。已经完成了在页面中添加了自定义插件,但是浏览器无法确定自定义组件的生命周期,如果通过以下方式声明则使自定义组件生命周期变得清晰了。

el.innerHTML = '<div data-my-widget></div>';

因为这不是一个内置的组件,我们现在必须手动实例化新组件,

$(el).find('[data-my-widget]').myWidget();

避免这种复杂设置方法的有效方式是完全抽象DOM交互。不过,这个动作也比较复杂,需要创建框架或者库来自定义组件。

面临的问题

组件一旦被声明,占位符已经被替代为原生的HTML标记:

<div data-my-widget>

<div class="my-widget-foobar">

<input type="text" class="my-widget-text" />

<button class="my-widget-button">Go</button>

</div>

</div>

这样做的弊端是,自定义组件的标记和普通HTML组件的标记混杂在一起,没有清晰的分割和封装。这就不可避免的会出现命名及样式等冲突。

Web组件的产生

随着三方Web组件的发展,它已经成为了Web开发不可或缺的部分:

<!—导入: -->

<link rel="import" href="my-widget.html" />

<!—使用:-->

<my-widget />

在这个实例中,我们通过导入HTML来添加组件并且立即使用。

更重要的是,因为<my-widget />是浏览器原生支持的组件,它直接挂在浏览器的生命周期中,允许我们像添加原生组件一样添加三方组件。

el.innerHTML = '<my-widget />';

// 插件当前已经被实例化

当查看这个组件的HTML 源码,你会发现它仅仅是一个单一的标签。如果启用浏览器Shadow DOM 特性,才可以查看标签内的组件,你将会发现一些有趣的事情,

当我们谈论Web组件时,我们不是在谈论一门新技术。Web组件最初的目的是给我们封装能力,它可以通过自定义组件和Shadow DOM 技术来实现。所以,接下来,我们将着重介绍下这两项技术。介绍以上两个技术之前,我们最好先梳理下已知浏览器原生组件。

已知的HTML组件

我们知道组件可以通过HTML标记或JavaScript来实例化:

使用标记实例化:

<input type="text" />
document.createElement('input');
el.innerHTML = '<input type="text" />';

使用JaveScript实例化:

document.createElement('input') 

document.createElement('div')

添加带有属性的HTML标签:

// 创建带有属性的input标签...

el.innerHTML = '<input type="text" value="foobar" />';

//这时value属性已经同步

el.querySelector('input').value;

组件可以响应属性的变化:

// 如果我们更改value 属性值
input.setAttribute('value', 'Foobar');

//属性值会立即更改
input.value === 'Foobar'; // true

组件可以有内部隐藏的DOM结构:

<!—使用一个input实现复杂的日历功能-->
<input type="date" />

 // 尽管其内部结构比较复杂,但是已经封装成为一个组件
dateInput.children.length === 0; // true

组件可以使用子组件:

<!—可以给组件提供任意个 'option' 标签-->

<select>

<option>1</option>

<option>2</option>

<option>3</option>

</select>

组件可以为其子组件提供样式:

dialog::backdrop {

background: rgba(0, 0, 0, 0.5);

}

最后,组件可以有内置样式。和自定义插件不同,我们不需要为浏览器的原生控件引用CSS文件。

有了以上的了解,我们已经具备了解Web组件的基础。使用自定义组件和Shadow DOM,我们可以在我们的插件中定义所有这些标准行为。

自定义组件

注册一个新组件也比较简单:

var MyElement = document.register('my-element');

// 'document.register' 返回一个构造函器

你也许注意到上面的自定义组件名称包含一个连接符。这是为了确保自定义组件名称不和浏览器内置组件不冲突。

现在<my-element />这个组件具备了原生组件的特性,

所以,自定义组件也同样可以进行普通的DOM操作:

document.create('my-element');

el.innerHTML = '<my-element />';

document.create('my-element');

构建自定义组件

当前,这个自定义组件仅仅有框架,而没有内容,下面让我们向其中添加一些内容:

//我们将提供'document.register'的第二个参数:

document.register('my-element', {

prototype: Object.create(HTMLElement.prototype, {

createdCallback: {

value: function() {

this.innerHTML = '<h1>ELEMENT CREATED!</h1>';

}

}

})

});

在这个例子中,我们设置自定义组件的prototype,使用Object.create 方法创建一个继承于HTMLElement的对象。在这个方法中修改该组件的属性 innerHTML。

我们定义了createdCallback方法,在每次声明实例时调用。你同样可以有选择性的定义attributeChangedCallback、 enteredViewCallback 和leftViewCallback等方法。

目前为止我们实现了动态修改自定义组件内容的功能,我们仍然需要提供自定义组件的封装方法,用于隐藏其内部组件。

使用Shadow DOM实现封装

我们需要完善下createdCallback方法。本次,除了修改innerHTML之外,我们添加一些额外的操作:

createdCallback: {

value: function() {

var shadow = this.createShadowRoot();

shadow.innerHTML = '<h1>SHADOW DOM!</h1>';

}

}

在这个例子中, 你会注意到‘SHADOW DOM!’,但是查看源码时你会发现只有空白的<my-element /> 标签而已。这里使用创建Shadow Root 方法替代了直接修改页面。

Shadow Root中的任何组件,是肉眼可见的,但是和当前页面的样式和DOM API相隔离。这样就实现了自定义组件是一个独立组件的假象。

添加“轻量级DOM”

目前为止,我们的自定义组件是空标签,但是如果向其中添加内部组件会出现什么现象呢?

我们假设自定义组件包含的节点如下,

<my-element>

这是一个轻量级 DOM。

<i>hello</i>

<i>world</i>

</my-element>

一旦针对于这个组件的 Shadow Root 被创建,它的子节点不再存在。我们这些隐藏的子节点封装为轻量级DOM节点。

如果禁用了 Shadow DOM,上面这个例子仅仅会显示为:这是一个轻量级 DOM‘hello world’。

当我们在createdCallback方法中设置 Shadow DOM后,我们可以使用新增内容分配轻量级DOM组件到Shadow DOM 中。

createdCallback: {

value: function() {

var shadow = this.createShadowRoot();

// 子组件'i' 标签现在已经消失了

shadow.innerHTML =

‘轻量级 DOM 中的 "i" 标签为: ' +

'<content select="i" />';

//现在,在 Shadow DOM 中只有 'i' 标签是可以见的。

}

}

封装样式

Shadow DOM 最重要的作用是创建了和当前页面隔离的Web组件,使Web组件不受当前页面样式和JaveScript脚本的影响。

createdCallback: {

value: function() {

var shadow = this.createShadowRoot();

shadow.innerHTML =

"<style>span { color: green }</style>" +

"<span>I'm green</span>";

}

}

反之,在 Shadow DOM 中定义的样式也不会影响之外的标签样式。

<my-element />

<span>I'm not green</span>

揭露钩子的秘密

当隐藏自定义组件内部标记,有时也需要在当前页面对组件中的内部特定组件进行样式设置。

例如,如果我们自定义一个日历插件,在不允许用户控制整个插件的情况下,允许最终用户去定义按钮的样式。

这是其中的部分特性和伪组件:

createdCallback: {

value: function() {

var shadow = this.createShadowRoot();

shadow.innerHTML = 'Hello <em part="world">World</em>';

}

}

这是在当前页面设置自定义组件内部组件样式的方法:

my-element::part(world) {

color: green;

}

这部分内容介绍了封装web组件的基本方式。Shadow DOM 是我们可以任意修改Web组件中的标签。在例子中,我们设置了“World”的样式,但是使用者却无法判断它是<em>标签。

在你尝试自定义Web组件之前,需要确保浏览器的相关特性已经打开。如果使用 Chrome,在 Chrome 中打开chrome://flags ,并且开启“experimental Web Platform features”。

这仅仅是个开始

所有本文中介绍的内容,都是模拟一些简单的浏览器标准行为。我们已经习惯于和原生的浏览器组件进行交互,因此自定义组件的步骤并不是想象中的那个难。Web组件最终提供我们一种实现简单、一致、可复用、封装和组合部件的方法,这是一个有意义的开始。

 

时间: 2024-10-30 08:24:53

Web Components是不是Web的未来的相关文章

Web Components是个什么样的东西

前端组件化这个主题相关的内容已经火了很久很久,angular 刚出来时的 Directive 到 angular2 的 components,还有 React 的components 等等,无一不是前端组件化的一种实现和探索,但是提上议程的 Web Components 标准是个怎样的东西,相关的一些框架或者类库,如 React,Angular2,甚至是 x-tag,polymer 现在实现的组件化的东西和 Web Components 标准差别在哪里?我花时间努力地把现有的 W3C Web C

说说 web components

Web Components 的现状 到目前为止,w3c定义的web components已经包含了 Templates, 提供一个包含html,css,js的代码片段,类似于一般模板引擎里的视图 Custom Elements, 提供一个自定义html元素的接口,支持对现有html元素的扩展 Imports, 提供对模板或者自定义元素这些资源的加载支持 Shadow DOM, 提供一个对外隐藏的web片段,而且支持独立的样式,不会破坏文档内的样式 web 组件的技术规范的制定就是为了保证前端组

Programming Microsoft Office 2000 Web Components第一

第一章第二节 Office Web Components是什么? Office Web Components是一组的COM控件,设计的目的是为众多的控件容器提供交互的电子表格建模,数据报表和数据可视化功能.OWC库包含四个主要的组件:电子表格组件,图表组件,透视表组件和数据源组件.我们将在这一节中简要论述每个控件,然后在后续各章中讨论更多细节. 注释: COM也被称作ActiveX.当微软发明了术语"ActiveX"来描述COM技术时,我正在Visual Basic小组,这个术语使得我

Programming MS Office 2000 Web Components第二章第二节

web 第二章第二节 电子表格组件的高级功能 我们已经讨论了电子表格组件的大部分基本功能,现在让我们转向一些高级功能.大部分的这些高级功能Excel2000都不包含,因为这些是组件专门需要的特殊功能.而那些Excel2000中存在的功能,在电子表格组件中也被增强,使得可以提供一些新的功能. 属性绑定和实时数据 "属性绑定"是电子表格组件中最新奇的新功能之一,它是指控件能够将同一个web页面上其它对象的属性和方法用作单元值或公式参数的能力.电子表格控件使用标准的COM机制来实现绑定到属性

Programming Microsoft Office 2000 Web Components第一章

web 译者说明:<Programming Microsoft Office 2000 Web Components>是我从网上下载的一本讲述OWC技术的英文电子书,之所以要翻译这本书,是基于以下几个想法:1.阅读英文资料时常常会不求甚解,忽略很多细节和不容易阅读的句子,如果强迫自己逐句的翻译出来,则会对原来的英文资料有更加全面.详细和深刻的了解.2.可以锻炼自己在英语方面的能力.3.能够给其他需要这方面的资料的朋友提供一定的帮助. 这是本人初次进行这方面的工作,本人的技术和英文能力都很一般,

Programming Microsoft Office 2000 Web Components第一章第一节

web 第一章第二节 Office Web Components是什么? Office Web Components是一组的COM控件,设计的目的是为众多的控件容器提供交互的电子表格建模,数据报表和数据可视化功能.OWC库包含四个主要的组件:电子表格组件,图表组件,透视表组件和数据源组件.我们将在这一节中简要论述每个控件,然后在后续各章中讨论更多细节. 注释: COM也被称作ActiveX.当微软发明了术语"ActiveX"来描述COM技术时,我正在Visual Basic小组,这个术

Programming MS Office 2000 Web Components第一章第三节

web 哪里可以使用这些组件? 既然Office Web Components都是COM控件,您会很自然的希望它们能够在任何自称是COM控件容器的环境中工作.然而,理论和现实不总是一致的,尤其在软件世界里.微软公司创造了许多能够包含控件的环境(我们小组脱口就能说出了16个),而别的公司创造了许多其它的环境. 为了避免Office的测试小组发狂,我们针对不同的容器,进行不同的级别的Office Web Components测试.首先,我们挑选出那些我们认为人们使用的最多的容器,进行了充分的测试.然

《移动网页设计与开发 HTML5+CSS3+JavaScript》—— 2.8  Web组件:标记的未来?

2.8 Web组件:标记的未来? 在目前被大家称为Web组件(Web Component)的建议中,扩展HTML有了一个令人兴奋的新方法.Web组件是一组技术的总称,它们使用CSS和标记,旨在促使为Web应用程序创建丰富界面变得简单易行. 眼下,规范还处于起草阶段,会有很多的更改.所以在这里,我们就不谈论它了,第11章将会更详细地介绍Web组件.

一、Angular 2.0的变革之路-组件化 Web Components

Angular 2.0的变革之路 Angular 1.x从2009年到现在已经过了6个年头,虽然中间Angular1.x顺应前端思想加入了很多新的特性,例如在1.3版本加入的bindToController,在1.5版本加入的用于取代directive部分功能的component.然而从整体的设计思想来说,Web Components已经成为大势所趋,Angular的变革也就势在必行. Angular 2.0 放弃了对1.x版本的兼容,这也就意味着2.0版本没有了1.x版本的历史包袱.Googl