[TOC]
* * * * *
## 1 源代码文件
### 1-1渲染入口
~~~
src\strategy\index.js
~~~
### 1-2 渲染实现
~~~
src\strategy\parser\parseView.js
~~~
## 2 流程分析
### 2-1 渲染调用
~~~
src\dom\ready\scan.js
vm.$render = avalon.render(vtree)
~~~
> 调用avalon.render()
将虚拟dom树生成渲染函数vm.$render
### 2-2 渲染入口
~~~
src\strategy\index.js
function render(vtree) {
var num = num || String(new Date - 0).slice(0, 6)
var body = parseView(vtree, num) + '\n\nreturn vnodes' + num
var fn = Function('__vmodel__', body)
return fn
}
avalon.render = render
~~~
> vtree: avalon.lexer()解析生成的虚拟dom树
> 首先获取当前日期num
> 调用parseView(vtree,num)生成函数主体
> 调用Function()生成渲染函数
Function()见 基础原理的js对象
### 2-3 渲染函数生成
~~~
src\strategy\parser\parserView.js
function parseView(arr, num) {
num = num || String(new Date - 0).slice(0, 5)
var forstack = []
var hasIf = false
var children = 'vnodes' + num
var vnode = 'vnode' + num
// 节点数组声明 var vnodes11111=[]
var str = 'var ' + children + ' = []\n'
for (var i = 0; i < arr.length; i++) {
// 当前解析阶段
var el = arr[i]
// 虚拟文本节点
if (el.type === '#text') {
// 函数语句 var vnode1111 = {type:"#test",skipContent:true}
str += 'var ' + vnode + ' = {type:"#text", skipContent:true}\n'
// 检查是否包含{{}}的定界符
var hasDelimiter = rexpr.test(el.nodeValue)
if (hasDelimiter) {
// 存在定界符,解析定界符内容
var array = parseDelimiter(el.nodeValue)
// 返回的字符串栈
if (array.length === 1) {
// 单个界定符内容
var a = parseExpr(array[0].expr)
// vnode1111.nodeValue=结果
str += vnode + '.nodeValue = ' + wrapDelimiter(array[0].expr) + '\n'
} else {
// 多个界定符
a = array.map(function (el) {
return el.type ? wrapDelimiter(el.expr) : quote(el.expr)
}).join(' + ')
// vnode1111.nodeValue = String()
str += vnode + '.nodeValue = String(' + a + ')\n'
}
// vonde1111.fixIESkip = true
str += vnode + '.fixIESkip = true\n'
// vonde1111.skipContent = false
str += vnode + '.skipContent = false\n'
} else {
// 不存在界定符
if (rsp.test(el.nodeValue)) {
// vnode1111.nodeValue = " "
str += vnode + '.nodeValue = "\\n"\n'
} else {
// vnode1111.nodeValue = ' ';
str += vnode + '.nodeValue = ' + quote(el.nodeValue) + '\n'
}
}
// vnodes.push(vnode);
str += children + '.push(' + vnode + ')\n'
// 虚拟注释节点
} else if (el.type === '#comment') {
var nodeValue = el.nodeValue
// ms-for:注释性指令
if (nodeValue.indexOf('ms-for:') === 0) {
var signature = el.signature
// for栈存储
forstack.push(signature)
/*var $for = {
type:"#comment",
directive:"for",
skipContent:false,
signature:"$for",
start:childenr.length,
nodevalue:nodeValue;
}*/
str += '\nvar ' + signature + '= {' +
'\n\ttype:"#comment",' +
'\n\tdirective:"for",' +
'\n\tskipContent:false,' +
'\n\tsignature:' + quote(signature) + ',' +
'\n\tstart:' + children + '.length,' +
'\n\tnodeValue:' + quote(nodeValue) +
'\n}\n'
// 节点压栈 vnodes1111.push()
str += children + '.push(' + signature + ')\n'
// 调用for指令进行解析
str += avalon.directives['for'].parse(nodeValue, num)
// ms-for-end:注释性指令
} else if (nodeValue.indexOf('ms-for-end:') === 0) {
var signature = forstack[forstack.length - 1]
str += children + '.push({' +
'\n\ttype:"#comment",' +
'\n\tskipContent:true,' +
'\n\tnodeValue:' + quote(signature) + ',' +
'\n\tkey:traceKey\n})\n'
str += '\n})\n' //结束循环
if (forstack.length) {
var signature = forstack[forstack.length - 1]
str += signature + '.end =' + children + '.push({' +
'\n\ttype:"#comment",' +
'\n\tskipContent:true,' +
'\n\tsignature:' + quote(signature) + ',' +
'\n\tnodeValue:' + quote(signature + ':end') +
'\n})\n'
forstack.pop()
}
//插入普通JS代码
} else if (nodeValue.indexOf('ms-js:') === 0) {
str += parseExpr(nodeValue.replace('ms-js:', ''), 'js') + '\n'
//其他文本值
} else {
str += children + '.push(' + quote(el) + ')\n\n\n'
}
continue
// 虚拟元素节点
} else {
// ms-if指令处理
var hasIf = el.props['ms-if']
if (hasIf) { // 处理ms-if指令
el.signature = makeHashCode('ms-if')
str += 'if(!(' + parseExpr(hasIf, 'if') + ')){\n'
str += children + '.push({' +
'\n\ttype: "#comment",' +
'\n\tdirective: "if",' +
'\n\tnodeValue:' + quote(el.signature) + ',\n' +
'\n\tsignature:' + quote(el.signature) + ',\n' +
'\n\tprops: {"ms-if":true} })\n'
str += '\n}else{\n\n'
}
str += 'var ' + vnode + ' = {' +
'\n\ttype: ' + quote(el.type) + ',' +
'\n\tprops: {},' +
'\n\tchildren: [],' +
'\n\tisVoidTag: ' + !!el.isVoidTag + ',' +
'\n\ttemplate: ""}\n'
//ms-widget指令
var hasWidget = el.props['ms-widget']
if (hasWidget) {// 处理ms-widget指令
str += avalon.directives.widget.parse({
expr: hasWidget,
type: 'widget'
}, num, el)
hasWidget = false
} else {
var hasBindings = parseBindings(el.props, num, el)
if (hasBindings) {
str += hasBindings
}
if(el.children.length){
str += vnode + '.children = ' + wrap(parseView(el.children, num), num) + '\n'
}else{
str += vnode + '.template = ' + quote(el.template) + '\n'
}
}
str += children + '.push(' + vnode + ')\n'
if (hasIf) {
str += '}\n'
hasIf = false
}
}
}
return str
}
~~~
>[info] 1 虚拟文本节点渲染
~~~
if (el.type === '#text') {}
~~~
> 检查界定符{{}},
> 存在解析{{}}插值表达式
> 不存在直接保存
* * * * *
>[info] 2 虚拟注释节点渲染
~~~
else if (el.type === '#comment') {}
~~~
> ms-for:类注释解析
> ms-for-end:类注释解析
> ms-js:普通js代码解析
* * * * *
>[info] 3 虚拟元素节点渲染
~~~
else { }
~~~
> ms-if 指令处理
> ms-widget 指令处理
## 3 其他操作
## 4 总结
### 4-1 意义
解析虚拟dom树vtree,生成对应渲染函数
### 4-2 思路
主要包含三种虚拟节点的解析与生成
文本虚拟节点,注释虚拟节点,元素虚拟节点
### 4-3 参考
- 概述
- 框架目录
- 组件目录(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接口
- 框架心得
- 心:总体思路