资讯专栏INFORMATION COLUMN

Vue编译器解析compile源码解析

3403771864 / 383人阅读

  现在我们讲compileToFunctions 的使用方法,现在看看内容:

  // compile
  var compiled = compile(template, options);

  其实真正应该讲的就是 compile 函数。

  解析 compile

  上述代码在调用 compile ,其中模板字符串 template ,就是让选项参数 options 的第二个参数传递给 compile 函数,下面就是有关传递过去的options如下:

  {
  shouldDecodeNewlines,
  shouldDecodeNewlinesForHref,
  delimiters,
  comments,
  warn
  }

  compile 源码

  现在我们看看 compile 的源码。

  function createCompilerCreator(baseCompile) {
  return function createCompiler(baseOptions) {
  function compile(
  template,
  options
  ) {
  var finalOptions = Object.create(baseOptions);
  var errors = [];
  var tips = [];
  finalOptions.warn = function(msg, tip) {
  (tip ? tips : errors).push(msg);
  };
  if (options) {
  // merge custom modules
  if (options.modules) {
  finalOptions.modules =
  (baseOptions.modules || []).concat(options.modules);
  }
  // merge custom directives
  if (options.directives) {
  finalOptions.directives = extend(
  Object.create(baseOptions.directives || null),
  options.directives
  );
  }
  // copy other options
  for (var key in options) {
  if (key !== 'modules' && key !== 'directives') {
  finalOptions[key] = options[key];
  }
  }
  }
  var compiled = baseCompile(template, finalOptions); {
  errors.push.apply(errors, detectErrors(compiled.ast));
  }
  compiled.errors = errors;
  compiled.tips = tips;
  return compiled
  }
  return {
  compile: compile,
  compileToFunctions: createCompileToFunctionFn(compile)
  }
  }
  }

  ·首先可以看到:

  var finalOptions = Object.create(baseOptions);

  配置选项

  finalOptions的配置上的选项最终是要挂载在指定对象上,其中baseOptions包含编译器在运作的时候所需的配置选项。

  var baseOptions = {
  expectHTML: true,
  modules: modules$1,
  directives: directives$1,
  isPreTag: isPreTag,
  isUnaryTag: isUnaryTag,
  mustUseProp: mustUseProp,
  canBeLeftOpenTag: canBeLeftOpenTag,
  isReservedTag: isReservedTag,
  getTagNamespace: getTagNamespace,
  staticKeys: genStaticKeys(modules$1)
  };

  属性分别解析

  第一个属性: expectHTML 被设置为 true 。

  第二个属性:modules

  var modules$1 = [
  klass$1,
  style$1,
  model$1
  ];
  var klass$1 = {
  staticKeys: ['staticClass'],
  transformNode: transformNode,
  genData: genData
  };
  var style$1 = {
  staticKeys: ['staticStyle'],
  transformNode: transformNode$1,
  genData: genData$1
  };
  var model$1 = {
  preTransformNode: preTransformNode
  };

  我们一起来细细将属性:

  第三个属性:directives 值是三个属性 (model、text、html) 的对象,且属性的值都是函数。

  第四个属性:isPreTag 它是一个函数,其作用是通过给定的标签名字检查标签是否是 'pre' 标签。

  第五个属性:isUnaryTag 是一个通过makeMap生成的函数,该函数的作用是检测给定的标签是否是一元标签。

  第六个属性:mustUseProp 它是一个函数,其作用是用来检测一个属性在标签中是否要使用props进行绑定。

  第七个属性:canBeLeftOpenTag 一个使用makeMap生成的函数,它的作用是检测非一元标签,但却可以自己补全并闭合的标签。比如 div 标签是一个双标签,你需要这样使用<div> text </div>,但是你依然可以省略闭合标签,直接这样写:<div> text ,且浏览器会自动补全。但是有些标签你不可以这样用,它们是严格的双标签。

  第八个属性:isReservedTag 它是一个函数,其作用是检查给定的标签是否是保留的标签。

  第九个属性:getTagNamespace 它也是一个函数,其作用是获取元素(标签)的命名空间。

  第十个属性:staticKeys 它的值是通过以 modules 为参数调用 genStaticKeys 函数的返回值得到的。 其作用是根据编译器选项的 modules 选项生成一个静态键字符串。

  我们接下来继续看看baseOptions 中各个属性的作用,看看源代码。

  继续往下看:

  var errors = [];
  var tips = [];
  finalOptions.warn = function(msg, tip) {
  (tip ? tips : errors).push(msg);
  };

  finalOptions添加warn 方法

  我们在finalOptions加入warn 方法,有两个参数:

  msg 错误或提示的信息

  tip 用来标示 msg 是错误还是提示。

  warn选项主要用在编译过程中的错误和提示收集,如果收集的信息是错误信息就将错误信息添加到前面定义的errors数组里,如果是提示信息就将其添加到 tips 数组里。

  继续:

  if (options) {
  // merge custom modules
  if (options.modules) {
  finalOptions.modules =
  (baseOptions.modules || []).concat(options.modules);
  }
  // merge custom directives
  if (options.directives) {
  finalOptions.directives = extend(
  Object.create(baseOptions.directives || null),
  options.directives
  );
  }
  // copy other options
  for (var key in options) {
  if (key !== 'modules' && key !== 'directives') {
  finalOptions[key] = options[key];
  }
  }
  }

  上述代码主要检查 options 证明存在,options 主要是使用编译器编译模板时传递的选项参数,简单来说就是为调用 compileToFunctions 函数时传递的选项参数。

  而baseOptions理解为编译器的默认选项或者基本选项,options 是用来提供定制能力的扩展选项。上面的代码主要是将options 对象柔和到 finalOptions 中。

  现在说说两个特殊的属性处理

  modules: 假如 options.modules 存在,当在 finalOptions 对象上柔和进 modules 属性,想要组合并后的新数组就要用baseOptions.modules 和 options.modules 。

  directives: 对于directives 采用原型链的原理实现扩展属性对基本属性的覆盖。

  继续:

  var compiled = baseCompile(template, finalOptions); {
  errors.push.apply(errors, detectErrors(compiled.ast));
  }
  compiled.errors = errors;
  compiled.tips = tips;

  上面的代码调用了 baseCompile 函数,并分别将字符串模板(template),以及最终的编译器选项(finalOptions)传递了过去。

  compiled 是 baseCompile 对模板的编译结果因此上面代码就是为了让用通过抽象语法树来证明是否有存在错误表达,当利用 detectErrors 函数实现,利用compiled.ast 作为参数传递给 detectErrors 函数,最终就会返会一个包含所有错误数值的集合,最终通过这句代码将错误添加到errors。

  将收集到的错误(errors)和提示(tips)添加到compiled上并返回。

  baseCompile 函数是在 createCompilerCreator 函数调用时传递的实参。

  // `createCompilerCreator` allows creating compilers that use alternative
  // parser/optimizer/codegen, e.g the SSR optimizing compiler.
  // Here we just export a default compiler using the default parts.
  var createCompiler = createCompilerCreator(function baseCompile(
  template,
  options
  ) {
  var ast = parse(template.trim(), options);
  if (options.optimize !== false) {
  optimize(ast, options);
  }
  var code = generate(ast, options);
  return {
  ast: ast,
  render: code.render,
  staticRenderFns: code.staticRenderFns
  }
  });

  现在内容也基本上述完毕,后续更多精彩内容请多多关注。


文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/127805.html

相关文章

  • VUE源码--目录结构(一)

    摘要:源码目录结构打包相关的配置文件,其中最重要的是。主要是根据不同的入口,打包为不同的文件。这个目录下的代码逻辑会把文件内容解析成一个的对象。 源码目录结构 VUE 2.6.10 ├── scripts # 打包相关的配置文件,其中最重要的是config.js。主要是根据不同的入口,打 包为不同的文件。 ├── dist # 打包之后文...

    tuniutech 评论0 收藏0
  • Vue原理】Compile - 源码版 之 从新建实例到 compile结束的主要流程

    摘要:页面这个实例,按理就需要解析两次,但是有缓存之后就不会理清思路也就是说,其实内核就是不过是经过了两波包装的第一波包装在中的内部函数中内部函数的作用是合并公共和自定义,但是相关代码已经省略,另一个就是执行第二波包装在中,目的是进行缓存 写文章不容易,点个赞呗兄弟 专注 Vue 源码分享,文章分为白话版和 源码版,白话版助于理解工作原理,源码版助于了解内部详情,让我们一起学习吧研究基于 ...

    CODING 评论0 收藏0
  • vue-loader 源码解析系列之 整体分析

    摘要:笔者系贡献者之一官方说明简单来说就是将文件变成,然后放入浏览器运行。部分首先分析部分从做右到左,也就是被先后被和处理过了。源码解析之二源码解析之三写作中源码解析之四写作中作者博客作者微博 笔者系 vue-loader 贡献者(#16)之一 官方说明 vue-loader is a loader for Webpack that can transform Vue components ...

    icattlecoder 评论0 收藏0
  • 太原面经分享:如何在vue面试环节,展示你晋级阿里P6+的技术功底?

    摘要:假如你通过阅读源码,掌握了对的实现原理,对生态系统有了充分的认识,那你会在面试环节游刃有余,达到晋级阿里的技术功底,从而提高个人竞争力,面试加分更容易拿。 前言 一年一度紧张刺激的高考开始了,与此同时,我也没闲着,奔走在各大公司的前端面试环节,不断积累着经验,一路升级打怪。 最近两年,太原作为一个准二线城市,各大互联网公司的技术栈也在升级换代,假如你在太原面试前端岗位,而你的技术库里若...

    xiaoqibTn 评论0 收藏0

发表评论

0条评论

3403771864

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<