上兩篇Mvvm教程的熱度超出個人預期,不少碼友留言表揚同時但願我繼續出下一篇教程,當時我也半開玩笑說只要點贊超10就兌現承諾,沒想到還真破了10,因此就有了今天的文章。css
熟讀
【教學向】150行代碼教你實現一個低配版的MVVM庫(1)- 原理篇
【教學向】150行代碼教你實現一個低配版的MVVM庫(2)- 代碼篇html
本篇是在上兩篇的基礎之上對代碼進行進一步擴展,從而實現web component功能,因此讀者務必掌握mvvm的實現機制才能深刻理解本篇的內容(mvvm是web component的基石)。前端
目前市面上各大主流前端框架,凡事帶web component功能的,他們的設計水準基本都不入個人法眼,惟一看得上眼的是google的polymer,可是在某些API設計層面也顯得略微繁瑣(想了解polymer的朋友看一翻一下我專欄裏面10篇polymer入門系列教程)web
html提供的原生標籤,好比DIV, BUTTON, INPUT家族,Hx家族等等,這些就比如俄羅斯方塊裏的一塊塊標準積木,咱們稱它們爲stand componentsegmentfault
某一天這些積木不能知足你的需求了,被擴展或被組合造成了非基本形狀api
這些新形狀就是custom component,自定義組件!爲何要有component呢,好處是什麼呢?前端框架
1. 能夠複用 2. 結構清晰 3. 獨立開發
你稍微開動下腦筋就能分析出來了,我就不展開了。框架
在座的各位都寫過index.html麼?很簡單
主要就分紅3大塊內容,style, dom, scriptdom
<!--樣式--> <style> </style> <!--DOM UI--> <body> </body> <!--邏輯--> <script> </script>
而後外面用個<html></html>包裹mvvm
因此這期低配版web component庫設計目的很簡單,做爲一個開發人員,我但願在寫一個custom component的時候也能按照index.html的原生風格來寫,這是多麼的優雅,天然,沒有學習成本啊!
這也應該是無數人心目中的web component設計
因此,咱們的SegmentFault.js v2.0的Web Component的設計宗旨就是,儘可能接近原生的html結構和使用習慣,接近原生從而把學習成本降到最低,是我追求的東西
<!-- myComp.html //文件名仍是以.html結尾,天然 --> <sf-component> <style> <!--css--> </style> <template> <!-- any dom--> <template> <script> //js </script> <sf-component>
寫個具體的例子
<!-- myComp.html --> <sf-component> <style> button{ color:red; } p{ color:yellow; } </style> <template> <div> <input type="text" sf-value="this.message"/> <button sf-innerText="this.buttonName" onclick="this.clickHandler()"></button> <p sf-innerText="this.message"> </p> </div> </template> <script> this.message = "this is a component"; this.buttonName = "click me"; this.clickHandler = function(){ alert(this.message); }; </script> </sf-component>
一個Component的描述文件定義好了,那麼接下去就是如何引入它了。沿用上篇Mvvm中的風格,咱們給SegmentFault這個Class弄個registerComponent(tagName,compPath)方法,好比在index.html中
var sf = new SegmentFault(); sf.registerController("xxx",xxx); ... sf.registerComponent("my-comp","components/myComp.html"); ... sf.init();
而在父組件中咱們就能夠經過"my-comp"這個咱們剛剛註冊時起的標籤名來引入這個組件
<body> <div>...<div> <my-comp></my-comp> </body>
怎麼樣!四個字:乾淨利落
1. Mvvm 具有雙向綁定功能 2. Shadow Style 具備獨立的不污染全局的css功能 3. Communication 具備和父子兄弟組件通信的功能 4. 擁有生命週期 (屬於高級功能,本低配版庫不涉及)
Mvvm以前已經實現,咱們只要套用以前的實現便可
可能不少人對這個沒什麼概念,我沿用前文中的內容,好比咱們在component中定義了它的style,如
<!-- myComp.html --> <sf-component> <style> button{ color:red; } p{ color:yellow; } </style> <template> <div> ... </div> </template> <script> ... </script> </sf-component>
這裏咱們在<style></style>標籤中,定義了css,其中p和button的寫法在傳統觀念中都是會影響html頁面中全部的p元素和button元素的,這是咱們不但願發生的,咱們但願的是這個<style></style>標籤生效的做用域僅僅是在當前的,被定義的component中。這種有獨立做用域的css就叫Shadow Style。
要實現Shadow Style,其實有比較簡單的作法,本篇設計篇中不會涉及,你能夠趁此獨立思考下,待下篇看看是否與我不謀而合,或者有比我更加高級的方案。
即組件之間的通信,常常有人在sf中問到這個組件通信問題,其實這個問題是有比較標準的答案的,即3點
1. 父子通信: 父->子 經過 set 屬性, 子->父 拋事件 2. 兄弟通信: 大兒子 拋事件給 -> 父 -> set 小兒子 的屬性 3. 遠親通信: 走消息總線 (其實就在一個單例上搞事件機制)
要實現通信機制,其實也不復雜,主要就2個功能,1 父組件能夠set子組件的屬性, 2 組件能夠向外層拋事件,外層也能夠監聽組件拋出的事件,因此,咱們會如此設計這塊的內容,覺個例子,代碼說話
<body> <div>...<div> <my-comp sf-msg="vm.message" sf-oncustomevent="vm.customEventHandler"></my-comp> </body>
你們注意看,從父組件的角度,我可使用sf- + propertyName(這裏是msg) 來實現外部父組件對組件的賦值,並且還能使用sf-on + 自定義事件名稱(這裏是customevent) 對組件進行監聽。
換個角度,從子組件角度出發,我能夠被外部賦值,我能夠能夠向外部dispatch事件。
<sf-component> <style> //... </style> <template> <div> <div class="compClass"> <input type="text" sf-value="this.message" /> <button sf-innerText="this.buttonName" onclick="this.clickHandler()"></button> <my-comp2 sf-msg="this.message"></my-comp2> <p sf-innerText="this.message + ', hi Component1'"> </p> </div> </div> </template> <script> this.buttonName = "click me"; this.clickHandler = function () { alert(this.message); this.dispatchEvent("customevent", "hello world");//爲component的vm,內置一個dispatchEvent方法,用法和原生的事件機制一毛同樣。 }; Object.defineProperty(this, "msg", { set: function (value) { if (value) { this.message = value; } } }); </script> </sf-component>
使用Object.defineProperty能夠很大程度上知足咱們對set property的需求,另外再給component的vm掛載一個內置的函數this.dispatchEvent來發送自定義事件咱們就功德圓滿了。
你能夠給一個組件:由註冊->加載定義->顯示到DOM Tree->內容更新->從DOM Tree移除->銷燬 等一系時間節點定義他的生命週期,若是是作的比較考究的庫,你能夠把這這些時間節點的變動都一一貫用戶通知,或者提供api供用戶控制。本文設計的低配版庫閹割了這部分高級功能,咱們就是一教學向的庫,不整這些有的沒的。
至此,設計篇結束,主要介紹了一下本教學庫的設計理念和一些web component的基本概念,歡迎點贊收藏評論,投硬筆投香蕉
若是本文閱讀沒有問題,請繼續服用下一篇
【教學向】150行代碼教你實現一個低配版的MVVM庫(2)- 代碼篇
【教學向】150行代碼教你實現一個低配版的MVVM庫(1)- 原理篇
【教學向】150行代碼教你實現一個低配版的MVVM庫(2)- 代碼篇
【教學向】再加150行代碼教你實現一個低配版的web component庫(1) —設計篇
【教學向】再加150行代碼教你實現一個低配版的web component庫(2) —原理篇