[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.kancloud.cn/zmwtp/avalon2/136861)
[附:节点解析](http://www.kancloud.cn/zmwtp/avalon2/137551)
[附:渲染生成](http://www.kancloud.cn/zmwtp/avalon2/137552)
[主:同步刷新](http://www.kancloud.cn/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接口
- 框架心得
- 心:总体思路