Appearance
调试模板编译过程
模板html
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>compile</title>
</head>
<body>
<div id="app">
<!-- 静态根节点 -->
<h1>Vue<span>模板编译过程</span></h1>
<!-- 有插值表达式,不是静态根节点 -->
<div>{{ msg }}<p>hello</p></div>
<!-- 没有字标签,不是静态根节点 -->
<div>是否显示</div>
</div>
<script src="../../dist/vue.js"></script>
<script>
const vm = new Vue({
el: '#app',
data: {
msg: 'Hello compiler',
isShow: false
},
methods: {
handler () {
console.log('test')
}
}
})
</script>
</body>
</html>
设置断点
- 入口文件entry-runtime-with-compile.js中的compileToFunctions函数上设置断点
按F5刷新
开始调试
- 按F11进入compileToFunctions函数,按F10到check cache的部分
这个位置是使用字符串模板作为key来缓存中查找是否有编译好的渲染函数,如果有就直接返回,否则继续往下执行,这里首次渲染,还没有缓存的函数,所以继续向下执行.
- 执行到compile函数,开始编译模板
- 按F11进入compile函数,在这个函数中,首先合并options选项
- 继续往下找到baseCompile的执行函数,设置断点,并按F8执行到这个断点
- 按F11进入这个函数,这是模板编译的核心位置,三件事情,把模板字符串转换成ast对象,优化ast对象,把优化后的ast对象转换成字符串形式的代码.下面是第一件事情,将模板字符串转换成ast对象,可以看到ast对象里面有type,tag,属性,parent和children等,不过目前还没有static属性
- 执行完optimize之后可以看到,ast对象中添加了有关静态节点的属性
- 最大的div不是静态节点也不是静态根节点
- h1对象是静态根节点,里面有子元素还都是文本节点
- 第二个子div有插值表达式不是静态节点,也不是静态根节点
- 最后一个子div是静态节点,不是静态根节点,因为没有子元素只有文本节点
- 按F10执行完generate函数,可以看到code中有了生成的最终的代码
然后看参数ast,可以看到里面添加了一个属性是staticProcessed,已经处理完毕
- baseCompile函数已经执行完毕,回到compile函数中,记录编译的错误和信息,返回编译好的对象,compile执行完毕之后,会到入口函数compileToFunctions中,此时在createFunction中设置断点,F8执行到这里
- 按F11进入这个函数,这个函数通过 newFunction 转换成了匿名函数
- 执行完毕之后可以看到选项被转换成了匿名函数,同样staticRenderFns数组也调用这个函数转换成匿名函数,如图
- 最终把生成的结果缓存返回
- 返回之后将render和staticRenderFns存储到options的属性上,到此整个编译的过程就执行完毕