相信首次據說MVVM的人,心裏都是充滿疑惑的!這是個嘛???能幹嗎???javascript
MVVM是Model-View-ViewModel的簡寫。它本質上就是MVC (Model-View- Controller)的改進版。即模型-視圖-視圖模型。【模型】指的是後端傳遞的數據。【視圖】指的是所看到的頁面。【視圖模型】mvvm模式的核心,它是鏈接view和model的橋樑。它有兩個方向:一是將【模型】轉化成【視圖】,即將後端傳遞的數據轉化成所看到的頁面。實現的方式是:數據綁定。二是將【視圖】轉化成【模型】,即將所看到的頁面轉化成後端的數據。實現的方式是:DOM 事件監聽。這兩個方向都實現的,咱們稱之爲數據的雙向綁定。html
總結:在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的新特性糅合進去,以應對客戶日益複雜的需求變化。vue
對於第一次接觸的人看了上面的解釋以後,可能仍是似懂非懂,那麼讓咱們從基礎的看起吧,剛纔咱們說過MVVM是它本質上就是MVC的改進版。那麼MVC又是什麼?它爲何須要改進呢?java
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這種設計模式是如何一步步演變過來的。 react
爲何會有MVVM框架?jquery
在過去的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就爲你們介紹這麼多,但願對你有幫助。
走以前別忘了贊加關注喲!