問題:vue
一、MVVM 的定義程序員
M (Model): 數據來源,服務器上業務邏輯操做數據庫
V (View): 界面,頁面設計模式
VM (ViewModel): view 和 model 的核心樞紐,如 vue.js數組
Model 和 ViewModel 的雙向關係:服務器
一、 Model 經過 Ajax (服務器) 通訊,發送數據給 ViewModel網絡
二、 ViewModel 經過 Ajax (服務器) 通訊,回傳數據給 Model框架
View 和 ViewModel 的雙向關係函數
一、 ViewModel 的數據改變,會映射到 View(便可以即時改變 View 顯示的內容)設計
二、View 的內容改變,也會同時改變 ViewModel 對應的數據
二、對比MVC 和 MVVM
認識MVC: Controller 負責 將 Model 的數據在 View 中顯示出來(即 Controller 負責將 Model 的數據賦值給View),好比在controller中寫document.getElementById("box").innerHTML = data[」title」],只是尚未刻意建一個Model類出來而已。
M (Model): 模型,應用程序處理數據的部分,一般指從數據庫讀取數據
V (View): 視圖,界面, 應用工程處理界面顯示的部分,一般根據模型數據建立
C (Controller): 控制器, 應用程序控制用戶交互的部分,一般負責從View讀取數據,控制用戶輸入,向 Model 發送數據
斯坦福大學公開課上的這幅圖來講明,這能夠說是最經典和最規範的MVC標準
從上圖能夠看出: C能夠直接引用 V 和 M, V 和 M 不能(不該該)直接引用 C
View 和 Controller 之間的交互:
View 把事件傳遞給 Controller,Controller 至關於靶子,View 和 Controller 有兩種交互方式:一種是: target->action,另外一種是:協議->委託,委託有兩種方式 代理和數據源:代理是 should,will,did 等等的委託,數據源是 data,count 等等的委託
Model 和 Controller 之間的交互:
Model是數據管理者,可理解爲它直接和數據庫打交道,Model 和 View 應該是一種同步關係,即無論任什麼時候候只要 Model 的數據發生改變,View 顯示的內容也應該發生改變。咱們可關注 Model 的值發生改變而不用關心 Model 的網絡請求是否結束了,Controller 根本不關心Model從哪裏拿數據,Controller 的責任是把Model 最新的值賦值給View,Controller 關注的是Model 的值是否發生改變
MVVM 的誕生:
須要數據有M, 須要界面有V,把M 的數據給V顯示,因此有 C,可是咱們忽略了一個重要的操做:數據解析,在MVC 時代手機API數據比較簡單,極可能一步就解決,那時把數據解析交給 Controller完成,可是如今手機API 數據愈來愈複雜,數據解析就沒有那麼簡單了,若是繼續按照MVC 的設計思路,將數據解析放到C完成,C 將會變得至關臃腫。Controller 設計出來並非處理數據解析的,而是:一、管理本身的生命週期, 二、處理 Controllder 之間的跳轉, 三、 實現 Controller 容器。在MVC 沒有誰是負責處理數據解析的,那麼將由誰負責處理數據解析呢?沒有就建立一個新的類出來,開發者們專門爲數據解析建立出一個新的類:ViewModel,因而 MVVM就誕生了
MVVM 的實現:
在MVVM Controller 的存在感被徹底下降了,VM 的出現是Controller 存在感下降的緣由。VM 先拿到原始數據,通過數據解析,把結果給Controller,由於 Controller只須要 數據解析的結果而不關心過程,因此至關於 VM 把如何解析Model 的數據封裝起來了,C 根本不須要知道這個M 的存在,前提是有VM, 一旦在實現 Controller中遇到任何與Model(數據)有關的問題就找 VM
三、 數據雙向綁定的原理
雙向綁定是什麼意思?
雙向是指ViewModel中的data部分和View之間的雙向關係。
正向:數據驅動頁面
反向:頁面更新數據
綁定是指自動化處理,data改變了view隨之改變,反之也是。
不用像傳統方式那樣,經過onChange事件獲取用戶輸入,而後再經過改變innerHtml修改顯示。
雙向綁定的原理是什麼?能夠寫出來嗎?
雙向綁定都是依賴ES5中一個重要的API,Object.defineProperty。
正向:
Object.defineProperty的做用:
監聽到 data的變化,監聽到變化後會有個回調函數,在定義的時候直接寫回調函數,在Object.defineProperty回調函數寫明 view 和 data 的關聯關係,後續中data有變化就會自動根據你寫的關聯處理修改View的顯示內容。直接操做修改data是由於 Object.defineProperty 有 set 屬性
反向:
在view中輸入內容時,經過 input 事件(好比 onchange),修改 data。只不過這件事不須要咱們程序員本身去寫了,有些框架背後在作這件事,好比,在Vue框架中,可使用V-Model方便的關聯view和data。
Object.defineProperty()
定義:
Object.defineProperty() 方法是在一個對象新定義一個屬性,或者修改一個對象的現有屬性,返回修改後的這個對象(換句話就是 修改一個對象返回一個修改後的對象)
語法:
Object.defineProperty(obj, prop, descriptor)
參數:
obj:要在其上定義屬性的對象。
prop:要定義或修改的屬性的名稱。
descriptor:將被定義或修改的屬性描述符。
返回值:
被傳遞給函數的對象。
Object.defineProperty 與 Reflect.defineProperty 的區別:
Object.defineProperty是 ES5 的用法,返回的是一個對象
Reflect.defineProperty是ES6 的用法,返回的是一個布爾值
Object.defineProperty缺點:
四、 設計模式 (觀察者模式)
1. 監聽者 (Observer): 有一個監聽者(Observer),監聽 data發生的變化, (經過Object.defineProperty 的get 屬性從新遍歷,修改 get 和 set 操做,還會有一個遞歸的操做,若是操做的是一個子對象,會對這個子對象從新進行遞歸遍歷一遍保證全部的key值都是有 observer 對象的。)
2. 觀察者列表 (Dep): 數據的變化會觸發 Object.defineProperty 對象的set 屬性,set 會執行對觀察者列表的觸發,通知觀察者列表(Dep)
3. 列表會有一個更新函數,通知了它們,它們會自動調用 updated 更新函數,也就是 Dep 調用了 回調,這個 回調是 觀察者 (watcher)給的
4. 觀察者(watcher): watcher 拿到更新後的數據就能夠更新到 view了
5. 觀察者列表的updated 是怎麼傳進去的,是經過 watcher 的訂閱,watcher 往觀察者列表添加新的內容(監聽完後會有一步實例化 watcher 對象,想對A 操做,observer 完後會手動調用一下watcher,實例化watcher,watcher 會調用 get,檢測watcher全局變量是否有值,有值的話會調用 deep.target,把內容往 Dep添加)