笔者系 vue-loader 贡献者之一(#16)
前言
vue-loader 源码解析系列之一,阅读该文章之前,请大家首先参考大纲 vue-loader 源码解析系列之 整体分析
selector 做了什么
1 | const path = require('path') |
大家可以看到,selector的代码非常简单,
通过 parser 将 .vue 解析成对象 parts, 里面有分别 style, script, template。可以根据不同的 query, 返回对应的部分。
很明显那么这个 parser 完成了分析分解 .vue 的工作,那么让我们继续深入 parser
parser 做了什么
1 | const compiler = require('vue-template-compiler') |
同样的,为了方便读者理解主要流程,笔者去掉了部分代码。
从上面代码可以看到,.vue 解析的工作其实是交给了 compiler.parseComponent 去完成,那么我们需要继续深入 compiler。
注意,这里 vue-template-compiler 并不是 vue-loader 的一部分了,从 vue-template-compiler 的 npm 主页可以了解到, vue-template-compiler 是 vue 本体的一部分
并不是一个单独的 package。通过查看文档可知,compiler.parseComponent 的逻辑在 vue/src/sfc/parser.js 里。
源码如下
parseComponent 做了什么
1 | /** |
parseComponent 里面有以下变量
处理对象 sfc
把 .vue 里的 css, javaScript, html 抽离出来之后,存放到找个对象里面
变量 depth
当前正在处理的节点的深度,比方说,对于
<template><div><p>foo</p></div></template
来说,处理到foo
时,当前深度就是 3, 处理到</div>
时,当前深度就是 2 。currentBlock
当前正在处理的节点,以及该节点的 attr 和 content 等信息。
函数 start
遇到 openTag 节点时,对 openTag 的相关处理。逻辑不是很复杂,读者可以直接看源码。有一点值得注意的是,style 是用 array 形式存储的
函数 end
遇到 closeTag 节点时,对 closeTag 的相关处理。
函数 checkAttrs
对当前节点的 attrs 的相关处理
函数 parseHTML
这是和一个外部的函数,传入了 content (其实也就是 .vue 的内容)以及由 start和 end 两个函数组成的对象。看来,这个 parseHTML 之才是分解分析 .vue 的关键
跟之前一样,我们要继续深入 parseHTML 函数来分析,它到底对 .vue 做了些什么,源码如下
parseHTML 做了什么
1 |
|
深入到这一步,我想再提醒一下读者,selector的目的是将 .vue 中的 template, javaScript, css 分离出来。带着这个目的意识,我们再来审视这个 parseHTML。
parseHTML 整个函数的组成是:
一个 while 循环
在 while 循环中,存在两个大的分支,一个用来分析 template,一个是用来分析 script 和 style。
函数 advance
向前跳过文本
函数 parseStartTag
判断当前的 node 是不是 openTag
函数 handleStartTag
处理 openTag, 这里就用到了之前提到的 start() 函数
函数 parseEndTag
判断当前的 node 是不是 closeTag,同时这里也用到了 end() 函数
通过以上各个函数的组合,在while循环中就将 sfc 分割成了三个不同的部分,读者可以对比我的注释和源码自行解读源码逻辑。
顺便在这里吐个槽,很明显这里的 parseHTML 是函数名是有问题的,parseHTML 应该叫做 parseSFC 比较合适。
- vue-loader 源码解析之一 整体分析
- vue-loader 源码解析之三 style-compiler (写作中)
- vue-loader 源码解析之四 template-compiler (写作中)