Web Components 包含了多種不一樣的技術。你能夠把Web Components當作是用一系列的Web技術建立的、可重用的用戶界面組件的統稱。Web Components使開發人員擁有擴展瀏覽器標籤的能力,能夠自由的進行定製組件。但截至本文時間,Web Components依然是W3C工做組的一個草案,併爲被正式歸入標準,但這並不妨礙咱們去學習它。web
何爲Web組件?Web組件相對於Web開發者來講並不陌生,Web組件是一套封裝好的HTML,CSS,以及JavaScript,它最大的特色就是可複用。基本在每個網站上咱們均可以看到各式各樣的組件,例以下拉菜單、按鈕、圖片滾播、日曆控件等。慢着,既然咱們已經能夠實現web組件的封裝,那Web Component這傢伙出現的意義是什麼呢?Web Component回答道:「大家的實現方式不夠優雅也不夠完美,仍是看看個人吧」。編程
由於當咱們使用各類編程技巧對組件進行封裝時,一個沒法規避的事實是,組件的內部是可被訪問和影響的,例如咱們對樣式表進行改動時常常會擔憂影響到頁面組件的樣式。而經過Web Component封裝出來的組件,咱們能夠選擇讓組件的內部隱藏起來,也就是說,組件內部是與世隔絕的!瀏覽器
總的來講,Web Components包含以上四種技術,本文着重談談Custom Element,這也是Web component中最核心的部分。app
自定義元素是一個可由建立者來自定義接口的對象。在建立時咱們須要經過 document.registerElement() 來對自定義元素進行註冊。該方法會返回一個元素的構造器,經過該構造器咱們就能夠建立咱們的自定義元素的實例了。dom
var MyButton= document.registerElement('my-button'); document.body.appendChild(new MyButton());
實際上 document.registerElement(tag-name, prototype) 包含兩個參數:函數
tag-name: 自定義元素的標籤名,這個標籤名必須包含連字符'-',這樣作的母的是用以區分自定義元素和HTML規範的元素學習
prototype: 這是一個可選的參數,用於描述該元素的原型,在該元素中你能夠爲自定義元素進行接口的定義網站
var MyElement = document.registerElement('my-element', { prototype: Object.create(HTMLElement.prototype, { createdCallback: { value: function() { this.innerHTML = "<p>I'm a Custom Element</p>"; } } }) }); document.body.appendChild(new MyElement())
在上面的例子中,咱們經過Object.create()方法建立了一個繼承自HTMLElement的對象做爲自定義對象的原型,並設置了元素默認的 innerHTML ,若是你對Object.create()方法的第二個參數不熟悉,你最好先去查閱一下。實際上它的上面的例子跟下面給出的寫法的效果是同樣的:this
var MyElementProto = Object.create(HTMLElement.prototype) MyElementProto.createdCallback = function() { this.innerHTML = "<p>I'm a Custom Element</p>" } var MyElement = document.registerElement('my-element', { prototype: MyElementProto }) document.body.appendChild(new MyElement())
接着,在頁面上咱們能夠看到渲染出以下結構:spa
在上面的例子中咱們能夠看到自定義元素的原型上有一個 createdCallback 屬性,它的值是一個回調函數,在自定義元素被建立的時候被調用。實際上自定義元素在它的生命週期中可能會經歷如下幾種變化:
在自定義元素經歷上面某些變化時,不一樣的回調函數會被調用。這些回調函數被保存在一個名爲生命週期回調的鍵值對集合中。咱們可實現的回調函數總共有如下4種,其中 attributeChangedCallback 的回調函數中咱們能夠經過其參數訪問到操做的屬性名、老的屬性值、新的屬性值。
DOM:
<div id="modify"> <label class="CEgreen"><input type="radio" name="CEclass" value="green">green box</label> <label class="CEred"><input type="radio" name="CEclass" value="red">red box</label> </div>
JS:
var MyElement = document.registerElement('my-element', { prototype: Object.create(HTMLElement.prototype, { createdCallback: { value: function() { this.innerHTML = "<span>I'm a Custom Element</span>" } }, attributeChangedCallback: { value: function(property, oldValue, newValue) { this.innerHTML = "attribute '" + property + "' is modified to " + newValue } } }) }) document.body.appendChild(new MyElement()) var temp = document.querySelector("#modify") var myElement = document.querySelector("my-element") temp.addEventListener('click', function(e){ console.log(e.target.value) myElement.className = e.target.value })
另外,給自定義元素添加樣式和普通元素是同樣的,這是上面例子中爲自定義元素添加的樣式:
my-element {display: inline-block;margin-top: 20px;padding: 10px;font-size: 24px;}
這就是一個最基礎的自定義元素的實現了。若是咱們但願自定義元素內部不受外部樣式的影響,咱們須要使用Shadow Dom來對內部dom結構和樣式進行封裝。