一、Angular Elements 介绍
Angular Elements 是伴随Angular6.0一起推出的新技术。它借助Chrome浏览器的ShadowDom API,实现一种自定义组件。 这种组件可以用Angular普通组件的开发技术进行编写,学习成本低,当它构建好后生成一个打包的js文件。如果页面引入该Js文件 ,就相当于在页面中新增了一个标签,所以在任意框架中都可以使用新标签,就像它是原生div一样。
ShadowDom API 是谷歌自己一直强推的API,也一直未标准化的技术。2013年推出的chrome25中,就支持Shadow Dom v0的API,至今都没有其它浏览器附和谷歌的。2016年的chrome53时,谷歌又推出了Shadow Dom v1的API。v1版本似乎将成正式标准,就连Edge都是都示正在考虑。无论v0,v1版本,现在都是草案的状态,距离正式标准还很远。幸运的是,现在有个项目@webcomponents/custom-elements提供polyfill技术方案,能让其它浏览器提前用上该技术。
二、Angular Elements 使用实战
前不久看到项目**angular-elements-dashboard :**支持动态加载模块和动态加载外部的模块。其中加载动态外部模块就是先编译一个angular elements项目,然后动态把该bundle.js插入到页面中。于是我就尝试一下,看这个构建的angular elements 文件到底如果引入一个空白的页面中,引入后的组件在浏览器中又是如何呈现的。
Demo 源文件 在 码云:https://gitee.com/40288193/Angualr-elements-demo
页面结构:
**demo.html **
主文件是一个标准的html5页面
external-dashboard-tile.emulated.js
external-dashboard-tile.native.js
是angular elements 用两种组件封装的方式打包的结果,分别是ViewEncapsulation.Emulated和 ViewEncapsulation.Native封装。它们也是今天的测试主要对象。
custom-elements.min.js
@webcomponents/custom-elements 的文件,是Shadow Dom v1 的polyfill文件 。
如果用chrome53以后的浏览器的话,可以不引入它。如果是其它浏览器,它是必须的。
native-shim.js
如果angular elements项目打包时,tsconfig.json中,
编译参数 **target: "es5"**时, 所有的class都被编译为function,此时就必须引入该文件。
编译参数 **target:"es2015"**或更高级的模块时,则不需要引入它。
根本原因是,Shadow Dom v1的api 只支持自定义元素是一个class类型,不能是一个function。
zone.js
angular依赖的文件
页面代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Angular Elements 演示Demo</title>
<link rel="stylesheet" href="https://my.oschina.net//u/1540190/blog/1929672/bootstrap.min.css">
</head>
<body class="container">
<h1>Angular Elements 演示Demo</h1>
<div class="row">
<h3>原生JS插入一个自定义元素</h3>
<div id="byJs"></div>
</div>
<div class="row">
<h3>用jqyery插入一个自定义元素</h3>
<div id="byJquery"></div>
</div>
<script src="https://my.oschina.net//u/1540190/blog/1929672/zone.js"></script>
<script src="https://my.oschina.net//u/1540190/blog/1929672/custom-elements.min.js"></script>
<script src="https://my.oschina.net//u/1540190/blog/1929672/native-shim.js"></script>
<script src="https://my.oschina.net//u/1540190/blog/1929672/jquery.min.js"></script>
<script src="https://my.oschina.net//u/1540190/blog/1929672/external-dashboard-tile.native.js"></script>
<script>
// 新引入的external-dashboard-tile元素, 它有三个属性a,b,c,它展示为一个表格
// 原生JS插入
const dom = document.createElement("external-dashboard-tile"), byJs = document.getElementById("byJs");
dom.classList.add("col-sm-2");
dom.setAttribute('a', '' + Math.round(Math.random() * 100));
dom.setAttribute('b', '' + Math.round(Math.random() * 100));
dom.setAttribute('c', '' + Math.round(Math.random() * 100));
byJs.appendChild(dom);
// Jquery 插入
const $dom = $("<external-dashboard-tile>"), $byJquery = $("#byJquery");
$dom.addClass("col-sm-2");
$dom.attr("a", Math.round(Math.random() * 100));
$dom.attr("b", Math.round(Math.random() * 100));
$dom.attr("c", Math.round(Math.random() * 100));
$byJquery.append($dom);
// 定时去修改两个表格的某个列
setInterval(function () {
dom.setAttribute('b', '' + Math.round(Math.random() * 100));
$dom.attr("a", Math.round(Math.random() * 100));
}, 2000)
</script>
</body>
</html>
效果:
注意:上下两个组件中,a,b两个列是定时变化的。
三、Angular Elements应用页面的分析
代码逻辑估计小学生也看的懂了,分别用原生JS 和 jquery 两种技术,生成
当我引入external-dashboard-tile.emulated.js 文件时,它是angular模拟组件的方式插入页面的,就是自定义标签里直接嵌入了div,这种模式并不是真正的Shadow Dom ,它只是一种模拟手段,它通过引入_ng_content-c0的属性空间隔离css 样式。
当我引入external-dashboard-tile.native.js 文件时,就是用原生的方式引入了,看效果,页面上有了 #showdow-root节点,并且外部的bootstrap样式传递不进去了,造成组件的样式全无。
总结一下,通过使用两个种方式操作自定义元素和以前学习的内置元素的概念一模一样。 那么就是说一个angular elements技术打包好的组件可以: build once ,run any framework! 这个黑科技还是让人惊喜的。
Angular Elements的开发技术和Angular普通组件是一致的,像Input属性,Output事件, 依赖注入的支持, 内容投影的支持(这个好像要用
四、Angular Elements应用后记
组件封装方式分别是native,emulated 。按照以前看的文章说明,Native模式其实用的是Shadow Dom v0,并不是最新的技术,在2018.7.25号的6.1.0升级中,它又引入了新的封装方式ViewEncapsulation.Shadow 。它的目的是为了不改变Native的模式情况下,引入最新的Shadow Dom v1技术 ,而Native已经过时,不鼓励使用。详见 (#24718)
现在这种打包模式,对于一个最简单的组件,打包后体积是189kb,是非常之大的。据说伴随angular 7推出的ivy 渲染引擎能大大减小组件的构建体积,忘在哪个视频中看到说打包后可到10kb的量级,但现在找不到该说法的来源。现在angular的commit中,有一半都是关于ivy的提交,只需要大家静等angular 7.0的到来了!
现在相关资料还比较少,我也是看youtube视频学习的相关介绍,下面给大家几个学习资料
官方文档:https://www.angular.cn/guide/elements
视频 Elements in v6 and Beyond :https://www.youtube.com/watch?v=Z1gLFPLVJjY
示例项目angular-elements-dashboard:https://github.com/manfredsteyer/angular-elements-dashboard