[TOC]
* * * * *
## 1 源代碼文件
### 1-1 掃描入口
~~~
src/dom/ready/modern.js
~~~
### 1-2 掃描實現
~~~
src/dom/ready/scan.js
~~~
## 2 流程分析
### 2-1 注冊scan到domready
~~~
src/dom/ready/modern.js
avalon.ready(function(){
scan(document.body)
})
~~~
### 2-2 掃描入口
~~~
src/dom/ready/scan.js
function scan(nodes) {}
~~~
### 2-3 掃描流程
>[success] 下面代碼全在src/dom/ready/scan.js
* * * * *
>[info] 1 獲取節點$id
~~~
var $id = hasController(elem)
~~~
* * * * *
> hasController()在下面定義
分析可知獲取elem的的ms-controller屬性。
`<div ms-controller="test"></div>` 中
$id是test
* * * * *
>[info] 2 獲取$id對應vm
~~~
var vm = avalon.vmodels[$id]
~~~
> avalon生成的vm存儲在全局數組avalon.vmodles
> 以vm的$id索引vm對象。
> 這里在avalon.vmodels數組中獲取$id對應vm
* * * * *
>[info] 3 解析渲染
~~~
if (vm && !vm.$element) {}
~~~
> 查找$id對應的vm成功,
> 并且vm.$element不存在
> 進行掃描處理
~~~
cleanWhitespace(elem)
~~~
> 刪除空格,加速diff操作
~~~
var str = elem.outerHTML
avalon(elem).removeClass('ms-controller')
vm.$element = elem
~~~
> 獲取節點的outerHTML內容,
> 移除節點的class屬性ms-controller
> 將elem綁定到vm.$element,對應判斷條件的!vm.$element
~~~
var now = new Date() - 0
~~~
> 內容解析開始計時
~~~
var vtree = avalon.lexer(str)
~~~
> 解析str為虛擬dom樹
~~~
avalon.log('create primitive vtree', new Date - now)
~~~
> 控制臺輸出解析耗時
~~~
now = new Date()
~~~
> 生成渲染開始計時
~~~
vm.$render = avalon.render(vtree)
~~~
> 生成渲染函數
~~~
avalon.log('create template Function ', new Date - now)
~~~
> 控制臺輸出渲染耗時
~~~
avalon.rerenderStart = new Date
~~~
> 控制臺渲染開始時間
~~~
elem.vtree = vtree
~~~
> 保存虛擬dom樹到elem.vtree
~~~
avalon.batch($id, true)
~~~
> vm與視圖同步刷新
* * * * *
>[info] 4 掃描處理
~~~
else if (!$id) {}
~~~
> 本節點沒有$id,
~~~
scan(elem.childNodes)
~~~
> 繼續掃描子節點
## 3 其他代碼
### 3-1 遞歸刪除空白
~~~
var notWhitespace = /\S/
function cleanWhitespace(target) {
var keep
for (var i = 0; i < target.childNodes.length; i++) {
var node = target.childNodes[i]
if ((node.nodeType == 3) && (!notWhitespace.test(node.nodeValue))) {
keep = target.removeChild(node)
i--
}else if (node.nodeType === 1) {
cleanWhitespace(node)
}
}
if (target.childNodes.length == 0 && keep) {
target.appendChild(keep)
}
}
~~~
> target: 待掃描節點
* * * * *
> 遍歷target子節點,
> 根據節點node的類型nodeType進行不同處理
> nodeType為3(text節點)并且文本節點為空,刪除
> 這里的i--對應removeChild。
> nodeType為1(element節點)則遞歸進行處理
> 如果目標target刪除后子節點長度為0
> 則將子節點追加到target
### 3-2 全局scan接口
~~~
module.exports = avalon.scan = function (a) {
if (!a || !a.nodeType) {
avalon.warn('[avalon.scan] first argument must be element , documentFragment, or document')
return
}
if (getController(a)) {
avalon.warn('[avalon.scan] first argument must has "ms-controller" attribute')
return
}
scan([a])
}
~~~
> a:待掃描節點
* * * * *
> module.exports module導出功能
見基礎原理的 js模塊
> 第一個if檢測a是否為element節點。
> 第二個if檢測a節點內是否包含ms-controller屬性
> 最后調用scan([a]) 進入掃描
### 3-3 ms-controoler屬性操作
~~~
function hasController(a) {
return a.getAttribute('ms-controller')
}
~~~
> a:待掃描節點a
* * * * *
> 獲取a節點的ms-controller屬性
> `<div ms-controller="test"></div>`
* * * * *
~~~
function getController(a) {
if (a.getAttribute && hasController(a)) {
return true
}
//document.all http://www.w3help.org/zh-cn/causes/BX9002
var all = a.getElementsByTagName ? a.getElementsByTagName('*') : a.querySelectorAll('*')
for (var i = 0, node; node = all[i++]; ) {
if (hasController(a)) {
return true
}
}
return false
}
~~~
> a:待掃描節點a
* * * * *
> 檢測a節點中是否包含ms-controoler屬性
> 遞歸遍歷a節點及其子節點
## 4 總結
### 4-1 意義
scan()是模板掃描的入口
### 4-2 思路
scan()中**遞歸掃描**目標節點及其子節點
將掃描結果的保存到對應節點elem的vtree中
### 4-3 其他操作
scan()中
包含對VM創建結果數組`avalon.vmodel`的操作
包含 節點解析入口 `avalon.lexer()`
包含 渲染生成入口 `avalon.render()`
包含 同步刷新入口 `avalon.batch()`
具體分析見框架流程的
[主:VM創建](http://www.hmoore.net/zmwtp/avalon2/136861)
[附:節點解析](http://www.hmoore.net/zmwtp/avalon2/137551)
[附:渲染生成](http://www.hmoore.net/zmwtp/avalon2/137552)
[主:同步刷新](http://www.hmoore.net/zmwtp/avalon2/136862)
4-4 參考鏈接
[avalon1與avalon2的異同點](http://www.cnblogs.com/rubylouvre/p/5358820.html)
[avalon2學習教程01](https://segmentfault.com/a/1190000004882326)
- 概述
- 框架目錄
- 組件目錄(components\)
- 生成目錄(dist\)
- 測試目錄(karma\)
- 示例目錄(perf\)
- 主體目錄(src)
- 其他文件
- 框架流程
- 前:章節說明
- 主:模板掃描(avalon.scan())
- 主:VM創建(avalon.define())
- 主:同步刷新(avalon.batch())
- 附:節點解析(avalon.lexer())
- 附:虛擬DOM(avalon.vdomAdaptor())
- 附:渲染函數(avalon.render())
- 附:VM生成(avalon.masterFactory())
- 附:節點diff(avalon.diff())
- 主:界面事件(test)
- 框架工具
- 另:全局函數
- 另:全局正則
- 另:事件接口
- 另:組件接口
- 另:DOMApi
- 框架驅動
- D : 指令實現
- D:兼容處理
- 使用范例
- 基礎原理
- js模塊
- js對象
- js函數
- js數組
- js字符串
- dom接口
- 框架心得
- 心:總體思路