Ver código fonte

baseOptions部分讲解,补充附录

HcySunYang 7 anos atrás
pai
commit
e5b3cbc926
3 arquivos alterados com 247 adições e 1 exclusões
  1. 1 0
      README.md
  2. 215 0
      note/7创建编译器.md
  3. 31 1
      note/附录/compiler-options.md

+ 1 - 0
README.md

@@ -25,3 +25,4 @@
 ##### [core/util 目录下的工具方法全解](/note/附录/core-util)
 ##### [platforms/web/util 目录下的工具方法全解](/note/附录/web-util)
 ##### [shared/util.js 文件工具方法全解](/note/附录/shared-util)
+##### [编译器选项整理](/note/附录/compiler-options)

+ 215 - 0
note/7创建编译器.md

@@ -419,6 +419,221 @@ if (process.env.NODE_ENV !== 'production') {
 
 #### compile 的作用
 
+回顾一下 `compileToFunctions` 函数中调用 `compile` 的方式:
+
+```js
+const compiled = compile(template, options)
+```
+
+很简单的一段代码,其中模板字符串 `template` 被透传了过去,选项参数 `options` 经过简单处理后继续作为第二个参数传递给 `compile` 函数,前面我们分析过,这里传递过去的 `options` 如下:
+
+```js
+{
+  shouldDecodeNewlines,
+  shouldDecodeNewlinesForHref,
+  delimiters,
+  comments,
+  warn  // 被 delete
+}
+```
+
+其中 `warn` 属性被 `delete` 操作符删除。这里只是给大家做一个简短的回顾,并且我们对 `Vue` 的编译器所接收的参数进行归纳,并整理了附录 [编译器选项整理](/note/附录/compiler-options),后面遇到的任何编译器选项都会整理到该附录里,大家可以在这里查阅 `Vue` 编译器所接收的选项。
+
+知道了这些我们就可以去看 `compile` 函数的代码了,我们知道 `compile` 函数是 `createCompileToFunctionFn` 函数的形参,也就是说,`compile` 函数是被从其他地方传递过来了,其实前面我们都分析过,这里的 `compile` 函数就是 `src/compiler/create-compiler.js` 文件中定义在 `createCompiler` 函数内的 `compile` 函数,如下:
+
+```js
+export function createCompilerCreator (baseCompile: Function): Function {
+  return function createCompiler (baseOptions: CompilerOptions) {
+    // 就是这个 compile 函数
+    function compile (
+      template: string,
+      options?: CompilerOptions
+    ): CompiledResult {
+      // 函数体 ...
+    }
+
+    return {
+      compile,
+      compileToFunctions: createCompileToFunctionFn(compile)
+    }
+  }
+}
+```
+
+可以发现,`compile` 函数接收两个参数,分别是模板字符串(`template`)和选项参数(`options`)。我们顺序的查看其函数体代码,首先是这句代码:
+
+```js
+const finalOptions = Object.create(baseOptions)
+```
+
+这句代码通过 `Object.create` 函数以 `baseOptions` 为原型创建 `finalOptions` 常量,`finalOptions` 才是最终的编译选项参数。这里的 `baseOptions` 是 `createCompiler` 函数的形参,也就是在 `src/platforms/web/compiler/index.js` 文件中调用 `createCompiler` 传递过来的参数:
+
+```js
+import { baseOptions } from './options'
+import { createCompiler } from 'compiler/index'
+
+const { compile, compileToFunctions } = createCompiler(baseOptions)
+```
+
+可以看到 `baseOptions` 来自于 `src/platforms/web/compiler/options.js` 文件,下面是该文件的全部代码:
+
+```js
+/* @flow */
+
+import {
+  isPreTag,
+  mustUseProp,
+  isReservedTag,
+  getTagNamespace
+} from '../util/index'
+
+import modules from './modules/index'
+import directives from './directives/index'
+import { genStaticKeys } from 'shared/util'
+import { isUnaryTag, canBeLeftOpenTag } from './util'
+
+export const baseOptions: CompilerOptions = {
+  expectHTML: true,
+  modules,
+  directives,
+  isPreTag,
+  isUnaryTag,
+  mustUseProp,
+  canBeLeftOpenTag,
+  isReservedTag,
+  getTagNamespace,
+  staticKeys: genStaticKeys(modules)
+}
+```
+
+还是比较简短的,这个文件的主要作用就是到处一个对象,即我们说到的 `baseOptions`,所以下面我们就把 `baseOptions` 这个对象的内容搞清楚。
+
+对象如下:
+
+```js
+{
+  expectHTML: true,
+  modules,
+  directives,
+  isPreTag,
+  isUnaryTag,
+  mustUseProp,
+  canBeLeftOpenTag,
+  isReservedTag,
+  getTagNamespace,
+  staticKeys: genStaticKeys(modules)
+}
+```
+
+我们一个一个看,第一个属性 `expectHTML` 被设置为 `true`。第二个属性是 `modules`,根据引用关系可知它来自于 `platforms/web/compiler/modules/index.js` 文件,打开这个文件:
+
+```js
+import klass from './class'
+import style from './style'
+import model from './model'
+
+export default [
+  klass,
+  style,
+  model
+]
+```
+
+以上是该文件的全部代码,可以发现 `modules` 实际上就是一个数组,数组有三个元素 `klass`、`style` 以及 `model`,且这三个元素来自于当前目录下的三个同名 `js` 文件。简单查看这三个文件的输出,如下:
+
+```js
+// klass.js 的输出
+export default {
+  staticKeys: ['staticClass'],
+  transformNode,
+  genData
+}
+// style.js 的输出
+export default {
+  staticKeys: ['staticStyle'],
+  transformNode,
+  genData
+}
+// model.js 的输出
+export default {
+  preTransformNode
+}
+```
+
+可以看到这三个文件输出的都是对象,且 `klass.js` 文件与 `style.js` 文件的输出基本相同,只有 `staticKeys` 字段有所区别,而 `model.js` 文件输出的对象只包含 `preTransformNode` 属性。最终 `platforms/web/compiler/modules/index.js` 文件将这三个文件的输出综合为一个数组进行输出,所以其输出的内容为:
+
+```js
+[
+  {
+    staticKeys: ['staticClass'],
+    transformNode,
+    genData
+  },
+  {
+    staticKeys: ['staticStyle'],
+    transformNode,
+    genData
+  },
+  {
+    preTransformNode
+  }
+]
+```
+
+以上就是 `baseOptions` 对象第二个属性 `modules` 的内容。`baseOptions` 对象的第三个属性是 `directives`,类似 `modules` 只不过 `directives` 来自于 `platforms/web/compiler/directives/index.js` 文件,该文件源码如下:
+
+```js
+import model from './model'
+import text from './text'
+import html from './html'
+
+export default {
+  model,
+  text,
+  html
+}
+```
+
+同样类似于 `modules` 输出,只不过 `directives` 最终输出的不是数组,而是一个对象,这个对象包含三个属性 `model`、`text` 以及 `html`,这三个属性同样来自于当前目前下的三个文件:`model.js`、`text.js` 以及 `html.js` 文件,我们分别查看这三个文件的输出:
+
+```js
+// model.js 的输出
+export default function model (
+  el: ASTElement,
+  dir: ASTDirective,
+  _warn: Function
+): ?boolean {
+  // 函数体...
+}
+// html.js 的输出
+export default function html (el: ASTElement, dir: ASTDirective) {
+  if (dir.value) {
+    addProp(el, 'innerHTML', `_s(${dir.value})`)
+  }
+}
+// text.js 的输出
+export default function text (el: ASTElement, dir: ASTDirective) {
+  if (dir.value) {
+    addProp(el, 'textContent', `_s(${dir.value})`)
+  }
+}
+```
+
+可以发现,这个三个文件分别输出了三个函数,所以最终 `baseOptions` 对象的 `directives` 属性如下:
+
+```js
+{
+  model: function(){},
+  html: function(){},
+  text: function(){}
+}
+```
+
+它是一个包含三个属性的对象,且属性的值都是函数。
+
+`baseOptions` 的第四个属性是 `isPreTag`,它是一个函数,可以在附录 [platforms/web/util 目录下的工具方法全解](/note/附录/web-util) 中查看其实现讲解,其作用是通过给定的标签名字检查标签是否是 `'pre'` 标签。
+
+
 
 
 

+ 31 - 1
note/附录/compiler-options.md

@@ -8,6 +8,36 @@
   shouldDecodeNewlinesForHref,
   delimiters,
   comments,
-  warn  // 被 delete
+  warn,  // 被 delete
+
+  // baseOptions
+  expectHTML: true,
+  modules: [
+    {
+      staticKeys: ['staticClass'],
+      transformNode,
+      genData
+    },
+    {
+      staticKeys: ['staticStyle'],
+      transformNode,
+      genData
+    },
+    {
+      preTransformNode
+    }
+  ],
+  directives: {
+    model: function(){},
+    html: function(){},
+    text: function(){}
+  },
+  isPreTag,
+  isUnaryTag,
+  mustUseProp,
+  canBeLeftOpenTag,
+  isReservedTag,
+  getTagNamespace,
+  staticKeys: genStaticKeys(modules)
 }
 ```