在前端MVVM框架設計及實現(一)中有一個博友提出一個見解:css
「html中使用mvvm徒增開發成本」html
我想這位朋友要表達的意思應該是HTML定義了大量的語法標記,HTML中放入了太多的邏輯,從而增長了複雜度前端
將邏輯放入HTML是一個很差的作法,也不建議這麼作,即使從複用的角度來說,由於HTML與代碼緊密耦合,要想從新組成一個應用程序很是困難git
固然,在構建一個應用程序時,你也能夠不使用框架,但不能否認,使用框架將使得你的開發工做變得更容易github
框架都不是萬能的,可是在某一種特定的項目中,用最方便快捷的方式達到一樣的目的又何樂而不爲呢?數組
指令瀏覽器
在第一節前端MVVM框架設計及實現(一)中,展現了用最簡單的代碼實現了一個雙向綁定的原理以及運做流程,可是若是是做爲框架來講那是遠遠不夠的,因此咱們須要慢慢的完善每個細節,若是要作到操做數據即操做行爲,那麼就意味着框架要在內部幫你作一大堆額外的事情,這裏面涉及的知識面足夠讓你跨入一個新的層次ruby
咱們先來初步完善第一個功能點:指令數據結構
若是用過 Angular,那麼你就會知道directive 是什麼框架
簡單點:利用聲明式的結構來控制佈局與行爲
<div id='box' ao-controller="box"> <div ao-css-width="w" ao-click='click' ></div> <p> {{ w }} {{ h }} {{ z }} </p> </div>
如圖ao-controller,ao-css-width等等HTML自己是沒有這語法結構的,那麼如何讓你將行爲關聯到HTML元素或者屬性上,甚至能讓你創造具備自定義行爲的新元素
爲了實現這種關聯,AngularJS取了一個高大上的名字經過引入HTML編譯器抽取這些標示能讓瀏覽器識別新的HTML語法,咋一看很高級仔細一想不就是一個模版引擎麼?
模版
此與彼同,此非彼也,一說模版就跑出來一個概念,佔位與變量替換,幾乎全部靜態模板的實現原理都是同樣的,將這個模板變成一個函數,而後裏面分紅靜態部分與動態部分,靜態部分就是上面的HTNMl部分,轉換爲一個個字符串,動態部分就是插入的JS代碼, 它們基本上原封不動地成爲函數體的邏輯。而後咱們傳入一個對象給這個函數,最後獲得一個符合HTML格式的字符串,最後用它貼到頁面上某個位置就好了。
靜態模板有幾個缺點,首先它容易混入大量的JS邏輯,對於菜鳥來講,他們特別喜歡在裏面放入愈來愈多JS代碼。這個在JSP年代,已經證實是bad practice。爲此出現了logic-less的 mustache。 其次,它更新視圖老是一大片一大片地處理,改動太大。最後,是因爲第2點引起的問題,它對事件綁定等不友好,由於一更新,原來的節點都被消滅了,須要從新綁定。幸虧,jQuery普及了事件代理,這問題纔沒有 暴露出來。
再次,字符串模塊沒有對樣式的操做,流程的操做進行封裝,沒有計算屬性,監控數組的東西,很容易誘導用戶在頁面上寫大量業務邏輯,致使代碼沒法維護。
MVVM引入一種叫DOM模塊,像knockout, avalon, angular就是用它們實現雙向綁定了,可維護性更高
可見
綁定屬性與插值表達式就是對應靜態模板中的JS邏輯部分,因爲只容許爲表達式或單個屬性值,複雜度被控制了,強制用戶將它們轉移到VM中。 VM做爲一個數據源,對應靜態模板的數據包,而且多了一個自動觸發功能,進化成一個消息中心。
實現細節
avalon經過scan執行dom的掃描,其實就是經過遍歷指定的節點樹拿到對應的HTML語法標記
咱們能夠經過controller劃分做用域,換句話說就是controller爲根節點是往內部層層遍歷檢測每一個元素上的語法標記
值得注意的細節,在IE67下,在循環綁定中,一個節點若是是經過cloneNode獲得,自定義屬性的specified爲false,沒法進入裏面的分支,
但若是咱們去掉scanAttr中的attr.specified檢測,一個元素會有80+個特性節點(由於它不區分固有屬性與自定義屬性),很容易卡死頁面
本章的代碼主要是實現簡單的HTML指令的解析,涉及到元素節點的attr屬性與文本節點的{{}}插值表達式,經過解析對應的語法標記生成指定的數據結構提供給以後使用
GitHub上會同步更新每章的實現,。。。敬請關注~