接上一章 執行流程1
在這一大堆掃描綁定方法中應該會哪些實現?
首先我們看avalon能幫你做什么?
- 數據填充,比如表單的一些初始值,切換卡的各個面板的內容({{xxx}},{{xxx|html}}, ms-html)
- 類名處理,如隔行變色,掠過變色(ms-class, ms-hover)
- 事件綁定(ms-click)
- 屬性處理(ms-checked, ms-href, ms-disabled)
- 數據格式化與驗證(過濾器與$watch)
- 將某個元素轉為一些功能更強大的UI,如果拖動塊,滑動塊,彈出層,顏色選擇器,手風琴,切換卡……
有了avalon,做登錄后無縫刷新頁面這樣操作毫無壓力
回顧到我們最開始的3個問題:
- 開發者沒有綁定任何事件
- 開發者沒有做任何多余的監控綁定
- 開發者沒有操作DOM代碼
由此可見在掃描綁定所匹配方法中就實現了,事件,dom,view,model,m等雙向綁定的最終操作
<p>First name: <input ms-model="firstName" /></p>
如圖以input的 ms-model綁定為例
分解后
modelBinding.INPUT = function(element, fn, scope) { //當value變化時改變model的值
var updateModel = function() { //data-observe="false" 跳過處理
if (god.data("observe") !== false) { fn(scope, element.value); } }; //當model變化時,它就會改變value的值
var updateView = function() { //先執行updateView
var neo = fn(scope); if (neo !== element.value) { //更新節點元素值
element.value = neo; } }; element.addEventListener("input", updateModel, false); //綁定事件
Publish[expose] = updateView; updateView.element = element; updateView(); delete Publish[expose]; }
仔細觀察:
提供2個處理方法,一個事件綁定,還有一堆不知名的東東(這里不考慮兼容問題)
具體簡單介紹下 : 以后會有詳細的源碼分析
Publish[expose]這是個臨時的收集東東,用來處理依賴關系, 比如說
- 定義了ms-model ="firstName" ,那么在哪些地方會用到它這個就是依賴,比如后面的插值表達式中就有{firstName}
<p>First name: <input ms-model="firstName" /></p> 定義 firstName 監控屬性
<div>{{firstName +" | "+ lastName }}</div> 關聯依賴 這里又關聯
- updateView();從名字就能知道它是用來更新視圖的,通俗的說就是把用戶定義的值給插到html結構中
定義的HTML結構 <p>First name: <input ms-model="firstName" /></p> 通過updateView 變成了 <p>First name: 正妹</p>
還有文本掃描,基本類似這樣一下來所有M中定義的數據就給替換到了view了,並且綁定好事件及處理的回調方法,OK.以上是靜態的時候處理的流程.
然后用戶交互的時候:
用戶比如在input中輸入:
在開始掃描的時候呢element.addEventListener("input", updateModel, false); //綁定事件
這個input元素就已經在后台給綁定好事件了
所以用戶輸入就等於直接執行了updateModel回調
updateModel簡單分解
方法分解:
fn(scope, element.value); 就處理一個回調方法
fn回調處理方法中包含了一堆的依賴關系
var fn = Function("scope", "value", "if(arguments.length === 1){" +
";return scope." + name + "" +
" }else{" +
" scope." + name + " = value;" +
" }");
fn 是一個new Function方法
fn 內部的實參數值有2個
fn 提供修改與設置
*重點
scope.name 與 scope.name = value; 都是從scrope(vm模型中獲取)
vm模型是被轉換過的對象,對屬性的操作都會調用set get方法也就是,當然這個地方有點繞
//生成defineProperties需要的配置屬性
Descriptions[name] = { set: accessor, get: accessor, enumerable: true };
簡單的來說,給模型中的屬性(賦值或者取值)就會調用accessor方法,而不是簡簡單單的賦值操作(請注意!)
所以在執行accessor我們可以看到這樣一堆東西
看到了吧 $1371537226241就是收集的依賴列表
所以我們在直接這個方法的時候,依賴的東東也會一並執行,達到同步多個view的目的
整個流程大概就是這樣允許運作的,當然這只會是簡單的流程
實際上的代碼還有很多“精巧”的設計,值的學習!
以后會逐步一一分析.
MVVM是前端未來的發展方向,微軟有knockout, winjs等MVVM框架; 著名的.Net組件開發公司 Telerik 推出了一套基於 jQuery的MVVM UI庫kendoui; 谷歌組織開發angula
r;jQuery, rails,Sproutecore,Merb,Handlebars這幾個著名框架的核心成員,超級大牛Yehuda Katz推出了emberjs!
同樣的MVMM框架,angular是找大而面的道路,因此體積非常龐大,1.6-1.7萬行,由於avalon直接是使用VBS與Object.defineProperty等原生C++接口,比knockout那些包無數
層JS的方法快多了。在渲染時,雖然雙方都邊掃描都綁定,但遇到text, html綁定(這些綁定會改變DOM樹構造,增刪節點,導致reflow), avalon會使用零秒延遲,讓性能消耗低的
先執行再進行性能消耗大的(chrome等高級瀏覽器,直接使用HTML5的新屬性 hidden,把90%的reflow屏蔽了)。因此整體速度是knockout的百倍或幾百倍以上,這視頁面的復雜情況
,越復雜reflow越嚴重,knockout就越慘
avalon短小精悍,而且作者離我們近,第一時間能反饋問題
~~感謝正美帶來的好東東
@by Aaron