M,即model,一個普通的JS對象,多是後臺傳過來的,也多是直接從VM中拿到,即VM.$json。有關的這個$json的名字還在商討json
V,即View,HTML頁面,經過綁定屬性或插值表達式,呈現數據,處理隱藏,綁定事件或動畫等各類交互效果。V只與VM打交道。api
VM,即ViewModel,咱們經過avalon.define("xxx", function(vm){vm.firstName = "正美"}),這裏的vm是一個臨時的對象,用於定義,真正的VM是avalon.define方法的返回值。它上面的$json屬性就是M,能夠見VM處於一切的核心。咱們對VM的每個操做,都會向上同步到V,向下同步到M。而且出於節能低碳起見(減小對象的建立),咱們在生成M時,會重複利用VM中的一些屬性,好比vm的某個屬性是一個對象,那麼這個對象會直接搬到$json中。若它是一個數組,它裏面每一個元素爲對象,這些數組或對象都會直接$json中去,固然有時會修復一下(好比計算屬性會轉換一個簡單的數據類型)數組
在MVVM模式中,ViewModel是貫穿整個框架的樑柱閉包
咱們如今分析下整個代碼如何運做的一個流程:本文不討論具體實現,只討論流程框架
首先天然是HTML結構dom
<fieldset ms-controller="simple">
<legend>例子</legend>
<p>First name: <input ms-model="firstName" /></p>
<p>Last name: <input ms-model="lastName" /></p>
<p>Hello, <input ms-model="fullName"></p>
<div>{{firstName +" | "+ lastName }}</div>
</fieldset>
@ 與常規結構不一樣mvvm
@ 定義了不少自定義標籤 如何:ms-model ,ms-controller 動畫
@ 插值表達式 {{}}this
.........等等,具體請看api手冊spa
那麼接下來開發着定義JS
avalon.ready(function() { avalon.define("simple", function(vm) { vm.firstName = "司徒" vm.lastName = "正美" vm.fullName = {//一個包含set或get的對象會被當成PropertyDescriptor,
set: function(val) {//set, get裏面的this不能改爲vm
var array = (val || "").split(" "); this.firstName = array[0] || ""; this.lastName = array[1] || ""; }, get: function() { return this.firstName + " " + this.lastName; } }, vm.nick = { name: "暗黑之民" } }) })
大概理解下代碼的意思:
avalon.ready(function() { //這是domReady,至關於jQuery的 $(function(){})
var model = avalon.define( "aaa", [], function(vm) { //建立一個名字爲aaa的ViewModel vm.firstName = "司徒" //建立一個監控屬性 vm.lastName = "正美" //建立一個監控屬性 vm.fullName = { //一個包含set或get的對象 用於建立一個依賴監控屬性 avalon.scan(); //開始掃描DOM樹,處理綁定
第二步就能看出來這個就是定義的一個模型了,vm->ViewModel 視圖模型
整個運做都是圍繞着vm展開的,mvvm模式中VM處於一切的核心,咱們對VM的每個操做,都會向上同步到V,向下同步到M。
VM的建立不單單只是咱們看到的定義了幾個屬性,幾個方法,其實框架內部幫咱們作了不少事:
VM模型的建立:
1.框架內部建立模型對象VM
2.VM吸取開發定義的處理方法
3.把開發定義的方法給經內部的轉換,它的屬性與方法會換胎換骨
4.返回這個被改造過的模型對象,掛到全局保存起來
因此這個裏面涉及閉包與做用域鏈的問題了,之後再慢慢分析
那麼這個VM建立好了,咱們接下來幹嗎呢?
你們有沒有發如今HTML結構中與VM代碼中,有沒有共同點?
1.HTML中定義的自定義標籤與VM中的屬性方法名是否是同樣?
2.根據API的定義,HTML對應的每個標籤的都會對應着某一種JS的處理方式
3.如今HTML結構與JS代碼都是獨立的東東,因此咱們想個辦法讓他們關聯起來
如何關聯?
答案:掃描綁定
avalon.scan();
簡而言之呢就是掃描屬性節點,文本節點,找到對應的事件處理器,執行事件綁定等一堆東東
屬性節點
<input ms-model="firstName" />
發現有ms-開頭的名字就會解析成對應的一個處理方法
好比ms-model
//將模型中的字段與input, textarea的value值關聯在一塊兒 var modelBinding = bindingHandlers.model = function(data, scopes) { var element = data.element; var tagName = element.tagName; //是否有對應元素的標籤名的處理方法 if (typeof modelBinding[tagName] === "function") { var array = getValueFunction(data.value.trim(), scopes); if (array) { modelBinding[tagName](element, array[0], array[1]); } }
固然還會傳遞一些須要運行的參數
特別指出來傳遞的實參scopes就是ViewModel對象
* 在這一大堆掃描綁定方法中應該會哪些實現(這些方法纔是最終的執行體)
待續...