2019獨角獸企業重金招聘Python工程師標準>>>
一、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="./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="./zone.js"></script><script src="./custom-elements.min.js"></script><script src="./native-shim.js"></script><script src="./jquery.min.js"></script><script src="./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>元素,并且設置元素的class 和 屬性,最后插入到頁面上。? ?最后寫個定時器,分別用兩種技術定時修改它們的一個屬性。
? ? ? ?當我引入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事件,? 依賴注入的支持, 內容投影的支持(這個好像要用<slot> 來做)? ,總之并沒有因為?Angular Elements需要脫離ng環境,沒有Module 沒有Route等支持,它就閹割功能,添加限制。沒有,全部沒有, 這一點谷歌還是良心。
四、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