WebComponents是什么?它为什么对我们这么重要?sentsin/web/1089.html
原⽂链接 What are WebComponents and why are they important?
摘要
先看⼀看未来的 WebComponent 标准,再简单了解怎么写 WebComponents,最后说说它的重要性。
简介
这篇⽂章简单介绍 WebComponent 标准,介绍哪些浏览器已经开始⽀持 WebComponents,讨论 WebComponents 能解决什么问题,以及它对 web 开发的重要性。你可以了解到如何利⽤ Vanilla javascript 编写⼀个简单的 WebComponent,我还会针对它的潜在优势分享我⾃⼰的⼀些拙见。
什么是 web components ?
近年来,web 开发者们通过插件或者模块的形式在⽹上分享⾃⼰的代码,便于其他开发者们复⽤这些优秀的代码。同样的故事不断发⽣,⼈们不断的复⽤ javascript ⽂件,然后是 CSS ⽂件,当然还有 HTML ⽚段。但是你⼜必须祈祷这些引⼊的代码不会摧毁你的⽹站或者web app。WebComponents 是这类问题最好的良药,通过⼀种标准化的⾮侵⼊的⽅式封装⼀个组件,每个组件能组织好它⾃⾝的 HTML 结构、CSS 样式、javascript 代码,并且不会⼲扰页⾯上的其他代码。
The Shadow DOM
⼤家之前可能说过 shadow DOM,但 shadow DOM 到底是什么?开发者能通过 shadow DOM 在⽂档流中创建⼀些完全独⽴于其他元素的⼦ DOM 树(sub-DOM trees),由于这个特性,使得我们可以封装⼀个具有独⽴功能的组件,并且可以保证不会在不⽆意中⼲扰到其它DOM 元素。shadow DOM 和标准的 DOM ⼀样,可以设置它的样式,也可以⽤ javascript 操作它的⾏为。主⽂档流和基于 shadow DOM 创建的独⽴组件之间的互不⼲扰,所以组件的复⽤也就变得异常简单⽅便。
HTML 模板
只要你⽤过类似 Angular JS 之类的现代 javascript 框架,就⼀定对 HTML 模板再熟悉不过了。开发者通过模板来复⽤⼀些 HTML 代码段,在 HTML5 标准下我们甚⾄不需要 javascript 框架就能轻松使⽤模板。
导⼊ HTML 模板
在模板中创建 HTML 代码块和⼦ DOM 树,使得我们可以⽤不同的物理⽂件来组织代码。通过<link>标签来引⼊这些⽂件,就像我们在 PHP ⽂件中引⽤ javascript ⽂件那样简单。
⾃定义元素
我们声明⼀个语义化的⾃定义元素来引⽤组件,⽤ javascript 建⽴⾃定义元素和模板、shadow DOM 之间的关联,然后将⾃定义标签(例
如<my-custom-element></my-custom-element>)插⼊到页⾯上就能得到⼀个封装好的组件。Angular JS 中有很多类似的写法。
试写第⼀个 WebComponent
现在你应该已经对 WebComponents 有了⼀定的了解,但我想通过⼀个简单的例⼦能让你更好的理解上⾯那些枯燥的概念。以下代码展⽰了⼀个最简单的 WebComponent 由哪些元素组成,⽤<template>包裹 HTML 和样式代码,⽤ javascript 将这些绑定到⾃定义标签<favorite-colour>上。
<!-- WebComponent example based off element-boilerplate: github/webcomponents/element-boilerplate -->
<template>
<style>
.coloured {
color: red;
}
</style>
<p>My favorite colour is: <strong class="coloured">Red</strong></p>
</template>
<script>
(function() {
// Creates an object based in the HTML Element prototype
var element = ate(HTMLElement.prototype);
// Gets content from <template>
var template = document.currentScript.ownerDocument.querySelector('template').content;
/
/ Fires when an instance of the element is created
// Creates the shadow root
var shadowRoot = ateShadowRoot();
// Adds a template clone into shadow root
var clone = document.importNode(template, true);
shadowRoot.appendChild(clone);
};
prototype: element
});
}());
</script>
⽤<link />引⼊ WebComponent ⽂件,并添加<favorite-colour>标签将 WebComponent 添加到页⾯上,如下代码所⽰:
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>My First WebComponent</title>
<link rel="import" href="components/favorite-colour.html" />
</head>
<body>
<favorite-colour></favorite-colour>
</body>
</html>
这个简单的例⼦演⽰了如何创建⼀个易复⽤、可维护的 WebComponent。
WebComponent 兼容性
你可能会说:“确实很diao,但什么时候才能 '真正' ⽤得上呢?”。我会告诉你:“现在就能⽤了少年”。下⾯的表格列出了主流浏览器对WebComponent 中各个特性的兼容性。
意料之中的是基于 Blink 的浏览器在这⽅⾯处于领先地位。上表清晰的告诉我们,哪怕是最简单的 WebComponent 例⼦也必须⽤ Chrome 或 Opera 运⾏。
填补空缺
虽然⼤部分浏览器还不⽀持 WebComponent ,但是有个叫做 webcomponentsjs 的兼容库,可以让 WebComponent 在不⽀持它的浏览器上运⾏起来。只要你在项⽬中引⼊这个库,就可以像上⾯的例⼦那样将 WebComponents ⽤起来。
WebComponents 的重要性
WebComponents 将如何改变当前的 Web 开发模式?本⽂的开头已经给出了答案,“通过⼀种标准化的⾮侵⼊的⽅式封装⼀个组件”,但这究竟能带来哪些好处呢?
⽆害插件
本⽂的前⾯已经介绍了开发者可以通过 shadow DOM 创建⼦ DOM 树,并且不会被页⾯上的 CSS 样式和 javascript 脚本所影响。显⽽易见的好处就是当你引⼊⼀个第三⽅组件的时候,不⽤担⼼它会对你的⽹站其他功能造成影响。对于开发者来说,开发⽆害插件变得更简单了。下⾯的例⼦⽤刚才写的 WebComponent 展⽰了这种封装的独⽴性。在 WebComponent 内部定义了⼀个名为colour的类,并将color属性设置为 red 。在主页⾯中colour类的color为 green 并被设为!important,你会发现在 WebComponent 中的颜⾊还是展⽰为红⾊。你可以访问 Github 获取⽰例代码。
⼀劳永逸
标准的⽬的是增强通⽤性。⼀旦 WebComponents 被⼴泛⽀持起来,我们就能开发更通⽤的组件,⽽不⽤考虑其他项⽬⽤的是什么技术。再也不⽤针对 jQuery 写插件,再也不⽤为 Angular JS 写 directives,再也不⽤为 Ember.js 写 addons。⼀劳永逸,是 WebComponents 带来的最⼤好处。作为⼀个全职的 A
ngular JS 开发者,经常需要将 jQuery 插件翻译成 directives,然后才能在我的项⽬⾥⽤起来,这些⼯作⾮常繁琐。程序员不应该局限于某⼀种前端框架,但现实情况是我们正在被⼀个个前端框架所限制,因为不同框架的代码不能共享。WebComponents 能将我们从⽔深⽕热之中解救出来。
维护与测试
通过这样的标准编写的组件具有更好的可维护性。最佳实践能够更快的被采⽤,并给我们带来更快更可靠的 Web 应⽤。测试会变得更简单,测试规范也能随着组件⼀起发布。
Abstraction
我们可以在 WebComponents ⾥开发复杂的功能,就可以将较少的精⼒耗费在开发复杂 Web 应⽤上了。你只需要将这些组件组装起来,保证他们之间能够互相通信,就能组装出⼀个完整应⽤。以 Angular JS 1.x 为例,不需要写 controllers,不需要写 directives,不需要写那么多的 scope,只要提供⼀些基本的服务和路由就⾏。当然 Angular 2.0 已经将 WebComponents 规划进去了。
HTML 的故事
HTML 5 规范带来了⼀些新的语义化标签,例如<section>,nav。这以为着不⽤详细阅读代码细节就能了解开发者的意图。WebComponents 将彻底改变我们使⽤ HTML 的⽅式,在组件的 HTML 代码层⾯,
⾃定义元素和属性能表达更多语义。如下⾯的例⼦所⽰:
传统的 HTML 写法
<!-- PAGE NAVIGATION -->
<div>
<ul>
<li>Home</li>
<li>About</li>
<li>Contact</li>
</ul>
</div>
<!-- CONTENT AREA -->
<div>
<p>Here is some simple content in the content area.</p>
</div>
<!-- GALLERY -->
<div>
<img src="animage1.png" />
<img src="animage2.png" />
<img src="animage3.png" />
<img src="animage4.png" />
<img src="animage5.png" />
</div>
<!-- FOOTER -->
<div>
<p>A simple footer</p>
</div>
WebComponents 的语义化写法
<page-navigation data-position="top"></page-navigation>
<content data-theme="dark">
<p>Here is some simple content in the content area.</p>
</content>
webapp是什么架构<image-gallery data-fullscreen="true">
<img src="animage1.png" />
<img src="animage2.png" />
<img src="animage3.png" />
<img src="animage4.png" />
<img src="animage5.png" />
</image-gallery>
<footer>
<p>A simple footer</p>
</footer>
虽然上述例⼦⽐较简单,我们还是能从中看出两者的显著区别。第⼀个例⼦使⽤标准的 HTML 标签,很难直接从代码看出最终的渲染结果,⽽第⼆个例⼦使⽤了 HTML5 标签和⾃定义标签,从代码层⾯提供了更多有⽤信息。从这些具有语义的标签就能很快理解页⾯每⼀个区块的含义,例如page-navigation和footer。其它信息可以通过⾃定义属性传递,例如data-fullscreen和data-position这样的属性就很好的描述了它将传递给页⾯什么数据。
另⼀个⼤坑
上述的那些优点能让 Web 开发变得更美好,希望你跟我⼀样激动并满怀期待。但是...也有可能带来⼀些问题,历史⼀次次证明 Web 标准的实际应⽤可能会分裂为多个分⽀,给我们带来艰难的抉择,我担⼼这样的事情也会发⽣在 WebComponents ⾝上。⽬前已经有三个基于WebComponent 标准的框架,并且都很好的兼容低级浏览器。这本来是件好事,但也意味着我们开发 WebComponents 应⽤时有三个选择:X-Tag, Polymer, Bosonic。既然都是⽀持 WebComponent 标准,那么基于 Polymer 开发的组件代码能够⽤在 x-tag 组件⾥吗?反过来呢?看看下⾯的例⼦。
X-Tag 组件 (源码)
<!-- Import X-Tag -->
<script src="../bower_components/x-tag-core/src/core.js"></script>
<template>
<p>Hello <strong></strong> :)</p>
</template>
<script>
(function(window, document, undefined) {
// Refers to the "importer", which is index.html
var thatDoc = document;
// Refers to the "importee", which is src/hello-world.html
var thisDoc = document._currentScript.ownerDocument;
// Gets content from <template>
var template = thisDoc.querySelector('template').content;
lifecycle: {
created: function() {
/
/ Caches <strong> DOM query
this.strong = template.querySelector('strong');
// Creates the shadow root
this.shadowRoot = ateShadowRoot();
this.uiSetWho();
},
attributeChanged: function() {
this.uiSetWho();
}
},
accessors: {
who: {
attribute: {},
get: function(){
Attribute('who') || "World"
},
set: function(value){
}
}
},
methods: {
uiSetWho: function() {
// Sets "who" value into <strong>
Content = this.who;
// Removes shadow root content
this.shadowRoot.innerHTML = '';
// Adds a template clone into shadow root
var clone = thatDoc.importNode(template, true);
this.shadowRoot.appendChild(clone);
}
}
});
})(window, document);
</script>
Polymer 组件 (源码)
<!-- Import Polymer -->
<link rel="import" href="../bower_components/polymer/polymer.html">
<!-- Define your custom element -->
<polymer-element name="hello-world" attributes="who">
<template>
<p>Hello <strong>{{who}}</strong> :)</p>
</template>
<script>
Polymer('hello-world', {
who: 'World'
});
</script>
</polymer-element>
等等,看起来不对劲啊!我承认我还没有真正这两个框架开发过,有没有⼈能告诉我是在杞⼈忧天,但这看起来就真的是在⽤两种完全不兼容的⽅式开发 WebComponents。
我对 Angular 2 也有同样的担⼼,他们声称完全⽀持 WebComponent 标准,但显然还会有很多框架层⾯的东西。Angular 团队应该很清楚该怎么做并且为什么这么做,希望利⼤于弊吧。如果 Angular 团队成员能看到这篇⽂章,并向⼤家介绍 WebComponents 在 Angular 2 中的⽤法,那就再好不过了。
前⾯提到了语义化 HTML 标签的好处,我们通过阅读代码就能快速理解它的含义。当然这还取决于开发者是否使⽤语义化标签和语义化的⾃定义属性做开发。更重要的是,社区应尽快提供优秀的最佳实践来引导普通开发者形成更好的习惯。
总结
WebComponents 能彻底改变 Web 开发,但还需时⽇。前端社区需要做⼤量⼯作才能使 WebComponents 变得真正可⽤,才能让⼤家享受到组件式 Web 开发的便利。
你可以在 这个⽹站了解更多关于 WebComponents 的知识。他们的 GitHub 账号⾥有很多适合学习的例⼦,本⽂的例
⼦也来⾃其中。
我会很乐意到你们对本⽂的评论和对 WebComponent 的见解。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论