BiuJS是一個輕巧的mvvm框架
它實現了數據的雙向綁定
並提供一些基本的指令幫助你提高效率,好比$for
,$model
,$if
,$click
,$style
是的,如你所見,以$
開頭的指令是它的獨特標識
1000行左右的代碼量,讓應用的開發和加載biu的一瞬完成
BiuJS倉庫:https://github.com/veedrin/biu
首先咱們來看一下BiuJS是如何啓動的javascript
let app = new Biu({ mount: '#app', data: { me: 'BiuJS' }, action: { change: function() { console.log('changed'); } } });
mount
是BiuJS的掛載點,它決定BiuJS在多大範圍的DOM樹內起做用,而且它只能識別id選擇器html
data
是BiuJS的數據模型,頁面就是經過綁定這裏的數據實現自動更新的java
action
是BiuJS的方法集合,藉此實現行爲邏輯node
JavaScript提供了一個強大的接口Object.defineProperty
,經過它咱們能夠劫持對象的getter
和setter
git
也就是說,被劫持過的數據,若是值發生了變化,就會觸發setter
github
Object.defineProperty(data, key, { enumerable: true, configurable: true, get: function() { return value; }, set: function(newValue) { console.log('changed'); } });
假如咱們在setter
里加個回調函數,在回調函數中把新值寫進DOM裏,數據變化與頁面變化同步不就實現自動化了麼?數組
Object.defineProperty(data, key, { enumerable: true, configurable: true, get: function() { return value; }, set: function(newValue) { callback(newValue); } }); function callback(newValue) { node.innerHTML = newValue; }
對,這就是BiuJS的命脈所在,很簡單吧!app
不過,爲了進一步提高效率,咱們還有大量工做要作。接着往下看框架
若是數據變化要與多處頁面的變化同步,這時候就須要一個工具來統一接收更新了mvvm
咱們把DOM元素與回調函數打包在一塊兒,依次扔進一個數組裏,當數據觸發setter
的時候,再用一個函數遍歷這個數組,依次調用回調函數,一對多的同步自動化也被咱們實現了
Object.defineProperty(data, key, { enumerable: true, configurable: true, get: function() { return value; }, set: function(newValue) { notify(newValue); } }); function notify(newValue) { for (let i = 0; i < array.length; i++) { array.update(newValue); } }
這個行爲有點像送報紙,因此咱們稱之爲訂閱,訂閱的人再多,都不會手忙腳亂
看起來頗有道理,但是訂閱這個行爲究竟是怎麼實現的呢?
首先要明確一點,那個數組(訂閱清單)在數據那裏,不然setter
怎麼觸發數組呢!
因此咱們要遠程訂閱
還記得咱們有一個getter
嗎?它可不是吃乾飯的。只要咱們訪問數據的值,就會觸發getter
那咱們是否是能夠給getter
打個電話,讓它幫咱們訂閱呢?
getter
是個寂寞的老人,時不時的看望它一下,它什麼都會答應你
因此咱們只要訪問一下數據的值,而後在getter
裏把訂閱者push進數組裏,遠程訂閱就作到了
Object.defineProperty(data, key, { enumerable: true, configurable: true, get: function() { array.push(subscriber); return value; }, set: function(newValue) { console.log('changed'); } });
最後一個問題,DOM元素是如何與數據對應起來的?
它們倆是沒法溝通的,須要找個翻譯
把DOM元素裏的模板分析一下,找出裏面的變量和特定語法,這個過程叫模板編譯
舉個簡單的例子
<div>{{name}}</div>
咱們一眼就看出來,鬍子模板裏的name
是一個變量,程序可看不出來,除非你給它一套邏輯,這套邏輯就是編譯器
認出了name
,咱們才能夠到對應數據的數組裏添加訂閱
不然,上錯花轎可保不許嫁對郎哦
到這裏,整個流程纔算跑起來了
getter
,在對方的數組裏添加一個訂閱位setter
,遍歷數組,調用數組裏的全部回調有了這一套自動化系統,你只要把數據綁在模板裏,接下來頁面就活了
誒,不是說好了雙向綁定嗎?怎麼,是個瘸子呀?
你仔細想想,把數據與頁面綁定在一塊兒,這是毫無疑問可以實現的
可是把頁面與數據綁定在一塊兒,這是啥意思呢?
還真有辦法,就是輸入框。頁面能產生數據的地方也只有輸入框了
並且這個綁定也不稀奇,輸入框都有輸入事件,把獲取到的新值賦給數據就行了
<input class="input" type="text"> <div class="div"></div> <script type="text/javascript"> let input = document.querySelector('.input'); let div = document.querySelector('.div'); input.addEventListener('input', function(event) { div.innerHTML = event.target.value; }); </script>
這裏沒有數據的參與,但也能產生一個反向綁定的假象
雙向綁定就好像說,你看你美國挺強大,但我阿根廷足球也不賴呀,咱們結成對等的戰略合做夥伴吧!
因此恕我直言,雙向綁定實際上是個噱頭,重要的是訂閱
對了,咱們還須要提供一個統一的對外接口
當仁不讓,就叫Biu吧
用一個當即執行函數包裹,再把統一接口掛載到window
上,就能夠在外部使用了
(function(root) { function Biu(options) { this.mount = options.mount; this.data = options.data; this.action = options.action; } root.Biu = Biu; })(window);
以上就是BiuJS大致的結構
歡迎到BiuJS倉庫: https://github.com/veedrin/biu
瞭解詳情
更歡迎Star
和Fork