前端MVVM框架設計及實現(二)


在前端MVVM框架設計及實現(一)中有一個博友提出一個看法:

“html中使用mvvm徒增開發成本”

我想這位朋友要表達的意思應該是HTML定義了大量的語法標記,HTML中放入了太多的邏輯,從而增加了復雜度

將邏輯放入HTML是一個不好的做法,也不建議這么做,即便從復用的角度來講,因為HTML與代碼緊密耦合,要想重新組成一個應用程序非常困難

當然,在構建一個應用程序時,你也可以不使用框架,但不可否認,使用框架將使得你的開發工作變得更容易

框架都不是萬能的,但是在某一種特定的項目中,用最方便快捷的方式達到同樣的目的又何樂而不為呢?

 


指令

在第一節前端MVVM框架設計及實現(一)中,展示了用最簡單的代碼實現了一個雙向綁定的原理以及運作流程,但是如果是作為框架來說那是遠遠不夠的,所以我們需要慢慢的完善每一個細節,如果要做到操作數據即操作行為,那么就意味着框架要在內部幫你做一大堆額外的事情,這里面涉及的知識面足夠讓你跨入一個新的層次

我們先來初步完善第一個功能點:指令

如果用過 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上會同步更新每章的實現,。。。敬請關注~

Fork https://github.com/JsAaron/aaMVVM


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM