图片,vue 中有这样一张响应式系统的流程图,vue 会将模板语法编译成 render 函数,通过 render 函数渲染生成 Virtual dom,但是官方并没有对模板编译有详细的介绍,这篇文章带大家一起学习下 vue 的模板编译。,为了更好理解 vue 的模板编译这里我整理了一份模板编译的整体流程,如下所示,下面将用源码解读的方式来找到模板编译中的几个核心步骤,进行详细说明:,图片,这里我使用 webpack 来打包 vue 文件,来分析 vue 在模板编译中的具体流程,如下所示,下面是搭建的项目结构和文件内容:,如上 webpack.config.js 所示,webpack 可以通过 vue-loader 识别 vue 文件,vue-loader
是 webpack 用来解析 .vue
文件的 loader,主要作用是将单文件组件(SFC),解析成为 webpack 可识别的 JavaScript 模块。,搭建好整个目录项目后,执行 npm run build
,会将 vue 文件解析打包成对应的 bundle,并输出至 dist 目录下,下面是打包后的产出,对应 App.vue 的产物:,从上方的产物可以看出,App.vue 文件被编译分为三块,_App_vue_vue_type_template_id_7ba5bd90_scoped_true___WEBPACK_IMPORTED_MODULE_0__
、 _App_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__
,_node_modules_vue_loader_lib_runtime_componentNormalizer_js__WEBPACK_IMPORTED_MODULE_2__
,这三个模块恰好对应vue模板中的 template
、script
、style
这三个标签的模板内容,所以得出结论:vue-loader 会将 vue 模板中的template
、script
、style
标签内容分解为三个模块。为此,我找到 vue-loader 的源码,下面分析其源码逻辑:,源码里很清楚的可以看到 vue-loader 使用了 vue/compiler-sfc 中的 parse 方法对 vue 的源文件进行的解析,将模板语法解析为一段可描述的对象,对 descriptor
进行打印,输出结果如下,vue-loader 对源文件编译后,vue 模板会被转化成抽象语法树(AST),此处便是模板编译的入口,使用编译后的 AST 将 vue 模板拆分为 template 、script 和 style 三部分,方便后面 webpack 通过 resourceQuery 匹配分发到各个loader 进行二次解析编译,template 部分会被 template-loader 进行二次编译解析,最终生成render 函数。,template-loader
的作用是将 import { render, staticRenderFns } from "./App.vue?vue&type=template&id=7ba5bd90&"
模块编译成 render 函数并导出,以下是编译产物:,template-loader
核心原理是通过 vue/compiler-sfc
将模板转换成为 render 函数,并返回 template 编译产物,vue/compiler-sfc
是模板编译的核心库,在 vue2.7 版本中使用,而 vue2.7 以下的版本都是使用vue-template-compiler
,本质两个包的功能是一样的,都可以将模板语法编译为 JavaScript,接下来我们来解析一下在模板编译过程中使用的方法:,可以将 vue 文件中的模板语法转义为 AST,为后续创建 dom 结构做预处理,genElement
会将 AST
预发转义为字符串代码,后续可将其包装成 render 函数的返回值,通过genElement
函数包装处理后,将vue
模板的 template
标签部分转换为 render
函数,如下所示:,将 genElement
阶段编译的字符串产物,通过 new Function
将 code 转为函数,为了方便理解,使用断点调试,来看一下 compileTemplate 都经历了哪些操作:,首先会判断是否需要预处理,如果需要预处理,则会对 template 模板进行预处理并返回处理结果,此处跳过预处理,直接进入 actuallCompile
函数,这里可以看到本身内部还有一层编译函数对 template 进行编译,这才是最核心的编译方法,而这个 compile 方法来源于 createCompilerCreator
,图片,createCompilerCreator 返回了两层函数,最终返回值则是 compile 和 compileToFunction,这两个是将 template 转为 render 函数的关键,可以看到 template 会被解析成 AST 树,最后通过 generate 方法转义成函数 code,接下来我们看一下parse函数中是如何将 template 转为 AST 的。,图片,继续向下 debug 后,会走到 parseHTML 函数,这个函数是模板编译中用来解析 HTML 结构的核心方法,通过回调 + 递归最终遍历整个 HTML 结构并将其转化为 AST 树。,使用 parseHTML 解析成的 AST 创建 render 函数和 Vdom,图片,将 AST 结构解析成为虚拟 dom 树,图片,最终编译输出为 render 函数,得到最终打包构建的产物。,图片,到此我们应该了解了 vue 是如何打包构建将模板编译为渲染函数的,有了渲染函数后,只需要将渲染函数的 this 指向组件实例,即可和组件的响应式数据绑定。vue 的每一个组件都会对应一个渲染 Watcher ,他的本质作用是把响应式数据作为依赖收集,当响应式数据发生变化时,会触发 setter 执行响应式依赖通知渲染 Watcher 重新执行 render 函数做到页面数据的更新。,vue 2 官方文档 ( https://v2.cn.vuejs.org/ )
文章版权声明
1 原创文章作者:cmcc,如若转载,请注明出处: https://www.52hwl.com/29461.html
2 温馨提示:软件侵权请联系469472785#qq.com(三天内删除相关链接)资源失效请留言反馈
3 下载提示:如遇蓝奏云无法访问,请修改lanzous(把s修改成x)
4 免责声明:本站为个人博客,所有软件信息均来自网络 修改版软件,加群广告提示为修改者自留,非本站信息,注意鉴别