由淺入深講述MVVM


相信首次聽說MVVM的人,內心都是充滿疑惑的!這是個嘛???能干嘛???

MVVM是Model-View-ViewModel的簡寫。它本質上就是MVC (Model-View- Controller)的改進版。即模型-視圖-視圖模型。【模型】指的是后端傳遞的數據。【視圖】指的是所看到的頁面。【視圖模型】mvvm模式的核心,它是連接view和model的橋梁。它有兩個方向:一是將【模型】轉化成【視圖】,即將后端傳遞的數據轉化成所看到的頁面。實現的方式是:數據綁定。二是將【視圖】轉化成【模型】,即將所看到的頁面轉化成后端的數據。實現的方式是:DOM 事件監聽。這兩個方向都實現的,我們稱之為數據的雙向綁定。

總結:在MVVM的框架下視圖和模型是不能直接通信的。它們通過ViewModel來通信,ViewModel通常要實現一個observer觀察者,當數據發生變化,ViewModel能夠監聽到數據的這種變化,然后通知到對應的視圖做自動更新,而當用戶操作視圖,ViewModel也能監聽到視圖的變化,然后通知數據做改動,這實際上就實現了數據的雙向綁定。並且MVVM中的View 和 ViewModel可以互相通信。

 

 

 

MVVM 就是將其中的View 的狀態和行為抽象化,讓我們將視圖 UI 和業務邏輯分開。當然這些事 ViewModel 已經幫我們做了,它可以取出 Model 的數據同時幫忙處理 View 中由於需要展示內容而涉及的業務邏輯。MVVM(Model-View-ViewModel)框架的由來便是MVP(Model-View-Presenter)模式與WPF結合的應用方式時發展演變過來的一種新型架構框架。它立足於原有MVP框架並且把WPF的新特性糅合進去,以應對客戶日益復雜的需求變化。

 

對於第一次接觸的人看了上面的解釋之后,可能還是似懂非懂,那么讓我們從基礎的看起吧,剛才我們說過MVVM是它本質上就是MVC的改進版。那么MVC又是什么?它為什么需要改進呢?

MVC全名是Model View Controller,MVC是Model-View- Controller的簡寫。即模型-視圖-控制器。M和V指的意思和MVVM中的M和V意思一樣。C即Controller指的是頁面業務邏輯。使用MVC的目的就是將M和V的代碼分離。‘MVC是單向通信。也就是View跟Model,必須通過Controller來承上啟下。MVC和MVVM的區別並不是VM完全取代了C,ViewModel存在目的在於抽離Controller中展示的業務邏輯,而不是替代Controller,其它視圖操作業務等還是應該放在Controller中實現。也就是說MVVM實現的是業務邏輯組件的重用。由於mvc出現的時間比較早,前端並不那么成熟,很多業務邏輯也是在后端實現,所以前端並沒有真正意義上的MVC模式。而我們今天再次提起MVC,是因為大前端的來到,出現了MVVM模式的框架,我們需要了解一下MVVM這種設計模式是如何一步步演變過來的。 

為什么會有MVVM框架?

在過去的10年中,我們已經把很多傳統的服務端代碼放到了瀏覽器中,這樣就產生了成千上萬行的javascript代碼,它們連接了各式各樣的HTML 和CSS文件,但缺乏正規的組織形式,這也就是為什么越來越多的開發者使用javascript框架。比如:angular、react、vue。瀏覽器的兼容性問題已經不再是前端的阻礙。前端的項目越來越大,項目的可維護性和擴展性、安全性等成了主要問題。當年為了解決瀏覽器兼容性問題,出現了很多類庫,其中最典型的就是jquery。但是這類庫沒有實現對業務邏輯的分成,所以維護性和擴展性極差。綜上兩方面原因,才有了MVVM模式一類框架的出現。比如vue,通過數據的雙向綁定,極大了提高了開發效率。

(PS: 這里的MVP, MVVM甚至MXXX都只是MVC的變體而已,至於將重點放在C點還是V點(沒人會希望放到M點吧?!)就自然引出了若干種所謂的模式,其實模式只有一種,你稱為P也好VM也好,它都只是C的實例而已。總是設法弄出一些所謂的Business Word的家伙們,是前端開發最大的敵人!)

 又經過上面對MVC和MVVM的介紹,大家應該對他們應該有比較清楚的認識了吧。

 

在大家理解MVVM的概念之后,為了讓大家能更深入的理解MVVM,以便以后更好的運用,我們再說一些細節性的東西吧。

 

 

1. 雙向綁定

號稱是最難理解的地方,

 

 

標准的數據驅動開發,應該如上圖所示,在一個View的生命周期內,一個ViewModule會管理一個DomainObject(業務模型),一個DO可能包括多個Module數據模型,一個Module可能來自多個數據源,而不是想很多所謂的MVVM框架那樣強迫一個M來一個數據源

按照上圖標准分層方式來划分的好處,在於,邏輯清晰,Module層粒度夠細,可以被多次復用

DO層與VM層View層屬於一一對應關系,方便對數據做增刪改查的同步

每一層應該是獨立的,非一定要使用MVVM框架的緊耦合,可以用自己使用不同的js插件或者模塊實現MVVM

我們拋棄框架,單純的看數據,其實我們要解決的問題很簡單

a) 當DO對象屬性放生變化時候,通知View更新

b) 當View上表單值放生變化時,通知DO更新,並異步通知隊列同步到數據源

先來看問題a,這個最簡單,DO是一個基本的Javascript Object,我們在View上的模板顯示是這個Object.property,

改變一個Object對象的方式無非幾種,一種是

a) 顯示Object.property = ‘你好’

b) xxxx.methodName(Object, ‘property’,  ‘你好’)

c) xxxx.merge(Object, {‘property’:  ‘你好’})

如果是a的情況,ES5+,可以通過設置Object.defefineProperty(‘property’,{set: functiono(){},get:function(){}}),來做賦值和取值的監控觸發

對於IE8一下,因為js不支持運算符重載,所以暫時沒有好的辦法,所以如果只考慮移動端的話,直接defineProperty就全部搞定,如果是要考慮PC的話,就不建議開發者使用直接賦值的方式,參考java的開發模式,也是推薦OOP時候,使用set方式賦值,而不是直接=賦值。

當然了,如果你非要兼容IE8一下的話,用定時器做輪訓,配合for in 反射,通過臟數據與原始備份對比的方法也是一種辦法,不過這種辦法在當前頁面非常耗性能,由於IE8一下不支持多線程,HTML5 worker,如果未來flash 插件支持多線程的話,倒是可以用js和flash插件做線程交互的方式做臟數據檢測。

如果是b的情況,那就太簡單了,在methodName里面觸發對於該屬性修改的回調即可,如何注冊回調呢,首先我們要實現一個類似Dom Event的自定義對象的Event模型,然后通過類似Dom Event的注冊事件方式,注冊觀察者,訂閱事件,當執行了methodName時候,發送消息,通知所有訂閱者執行回調

如果是c的情況,類似b一樣處理

這樣一看,雙向數據綁定的問題就非常簡單的解決了。

我們再來看另外一個MVVM的問題,非簡單數據模型,復合數據模型(DO的屬性值不是一個string,而是一個Object,且這個Object可能還嵌套多層Obejct的時候)的處理辦法,這個一般的MVVM框架直接不考慮,或者通過長字段名的方式繞過這個問題

這個問題是這樣的,早在10幾年前,java structs框架流行的時候就出現了,當一個表單,出現需要對兩個Java Bean做update操作時候,一個bean是user,一個bean是成績

對應的表單字段名,就是 user表.name,user表.id,score表.point,

在struct2里面,處理邏輯是把 “點”作為特殊符號,在做form序列化時候,非包含點的字段的值都是string,包含點的字段是一個Object,比如剛才的form序列化之后結果就是 { user: {id :’’ , name: ‘’}, score: {id: ‘’, point: ‘’}}

同理在MVVM實現時,也是一樣,認為點是分割對象的關鍵字,這樣我們就可以實現把多個對象嵌套到View模板里面,實現復合Object的雙向映射。

 

最后再給大家介紹幾種常用的前端MVVM開發框架:Angular.js,react,vue。 (他們的區別我就不一一來說來,詳情可見 https://www.cnblogs.com/wdtzms/p/6557894.html。)
angular  谷歌
它的版本更新特別快,每次更新后,寫法都會有很多變化。現在國內依然還有很多公司在使用angular.js 1.X的版本。
react  facebook
是一個單項數據流的針對view層的框架,主要是做視圖渲染。代碼寫法相對簡潔。
vue 個人
vue是一個mvvm的框架,是現階段國內使用范圍最廣的一個,用這個框架一般比較輕松。純中文文檔,純中文社區,純中文交流,相關資源很好找。
 

關於MVVM就為大家介紹這么多,希望對你有幫助。

走之前別忘了贊加關注喲!

 

 

 
 
 
 


免責聲明!

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



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