Vue 2源码解析HTMLParserOptions.start函数方法

目录
  • HTMLParserOptions.start()
    • 处理后的 input ast element

HTMLParserOptions.start()

用来解析标签的开始部分(匹配到标签开始部分时调用),主要区分标签类型、解析标签指令配置与动态绑定参数等等。

let root
let currentParent
function start(tag, attrs, unary, start, end) {
  const ns = (currentParent && currentParent.ns) || platformGetTagNamespace(tag)
  if (isIE && ns === 'svg') attrs = guardIESVGBug(attrs)
  let element: ASTElement = createASTElement(tag, attrs, currentParent)
  if (ns) element.ns = ns
  if (__DEV__) {
    if (options.outputSourceRange) {
      element.start = start
      element.end = end
      element.rawAttrsMap = element.attrsList.reduce((cumulated, attr) ={
        cumulated[attr.name] = attr
        return cumulated
      }, {})
    }
    attrs.forEach(attr =invalidAttributeRE.test(attr.name) && warn(''))
  }
  if (isForbiddenTag(element) && !isServerRendering()) {
    element.forbidden = true
    __DEV__ && warn('')
  }
  for (let i = 0; i < preTransforms.length; i++) {
    element = preTransforms[i](element, options) || element
  }
  if (!inVPre) {
    processPre(element)
    if (element.pre) inVPre = true
  }
  if (platformIsPreTag(element.tag)) inPre = true
  if (inVPre) processRawAttrs(element)
  else if (!element.processed) {
    processFor(element)
    processIf(element)
    processOnce(element)
  }
  if (!root) {
    root = element
    if (__DEV__) checkRootConstraints(root)
  }
  if (!unary) {
    currentParent = element
    stack.push(element)
  } else {
    closeElement(element)
  }
},

start 函数在解析完标签的开始部分后被调用,接收的五个参数分别是:标签名 tag,标签的属性数组 attrs,是否自闭合 unary,起点位置 start,结束位置 end

  • 进入函数之后,首先会验证 当前元素的父元素的标签命名空间(svg,math或者undefined),如果是 svg 元素,还会对解析出来的 attrs 对象进行处理,去掉 svg 标签定义属性(xmlns 之类的属性)
  • 调用 createASTElement(tag, attrs, currentParent) 方法创建当前元素对应的 AST 对象 element。此时结构如下:
{
  type: 1,
  tag: tag,
  attrsList: attrs,
  attrsMap: makeAttrsMap(attrs),
  rawAttrsMap: {},
  parent: currentParent,
  children: []
}
  • 在开发环境下,还会将节点在字符串中的位置与节点原有的属性进行记录,并且 校验属性名 是否合法(禁止空格,引号,尖括号,反斜杠和等号)
  • 校验标签合法性,如果是 style,script 之类的标签会被标记为“被禁止”(element.forbidden = true
  • 遍历 preTransforms 数组配置的处理函数,分别处理当前节点的 ast 结果,并重新更新节点的 ast 对象(这里只处理 input)

处理后的 input ast element

这里处理后的 input ast element,会比基础的 ast element 要多一些属性:

{
attrs: [],
attrsList: [],
attrsMap: { 'v-model': 'xxx' },
chidlren: [],
derectives: [{ isDynamicArg: false, modifiers: undefined, name: 'model', rawName: 'model', value: 'xxx' }],
events: {
 input: { dynamic: undefined, value: "if($event.target.composing)return;xxx=$event.target.value" }
},
hasBindings: true,
parent: currentParent,
plain: false,
props: [{ dynamic: undefined, name: 'value', value: '(xxx)' }],
rawAttrsMap: {},
static: false
}

虽然上面也省略了几个属性和部分属性值,但是重点属性都在里面。在 preTransforms 过程中,实际上是通过 preTransformNode() 函数处理 input 标签,并且该标签具有 v-model 配置,没有 v-model 时直接退出。

之后会判断该元素是否有动态绑定类型,如果是 动态绑定的元素类型,则会增加一个 ifConditions 配置,内部会填充 checkbox, radio 和 其他 input 类型的标签,用来根据不同的情况显示不同的展示形式(个人理解这里为什么只有三种,是因为 checkbox 和 radio 与其他的 input 输入框差别比较大,而且需要 label 标签配合)

  • 判断元素有没有设置 v-pre 指令或者是一个 pre 标签,重新设置 inVPre, inPre 的状态
  • 如果此时 inVPre === true,则直接跳过这个节点内部的编译;否则会依次判断 v-for,v-if 和 v-once 配置并进行编译

这里会先判断 for 循环再判断 if 条件,所以才有 for 的优先级高于 if。

如果存在 v-for,会在 ast 对象中添加 forforProcessed 属性,并解析条件;如果内部有文本节点要显示循环的值,则会在标签最末级创建一个文本节点并绑定显示条件

如果存在 v-if,会在 ast 对象中添加 ififProcessed 属性,并添加一个 ifConditions 属性,存放不同条件下的 ast 节点对象和渲染条件

如果有 v-once,一样会在 ast 对象中添加 onceonceProcessed,并且会标记 staticProcessed

  • 上面的过程执行完之后,如果此时外部的 root 是 undefined,则会将当前的节点作为根元素赋值给 root,并调用 checkRootConstraints 检查根节点
  • 如果当前节点是一个自闭合标签,则直接调用 closeElement 结束该节点;不然则将该节点赋值给 currentParent 并插入 stack 解析栈,以供子节点的解析

以上就是Vue 2源码解析HTMLParserOptions.start函数方法的详细内容,更多关于Vue HTMLParserOptions.start的资料请关注我们其它相关文章!

(0)

相关推荐

  • vue parseHTML函数源码解析 AST预备知识

    目录 正文 createASTElement函数 解析指令所用正则 parse 函数中的变量 正文 接上章节:parseHTML 函数源码解析AST 基本形成 在正式扎进Vue parse源码之前,我们先了解下他周边的工具函数, 这能帮我们快速的去理解阅读. 还记得我们在上章节讲的element元素节点的描述对象吗? var element = { type: 1, tag: tag, parent: null, attrsList: attrs, children: [] } 在源码中定义了一

  • Vue 2源码解析Parse函数定义

    目录 Parse 函数 parseHTML Parse 函数 在 baseCompile() 执行过程中,首先就是通过 parse方法 解析 template模板字符串,生成对应的 AST 抽象语法树. 整个 parse函数 定义太长,这里省略几个内部方法 /** * Convert HTML string to AST. */ export function parse(template: string, options: CompilerOptions): ASTElement { warn

  • vue parseHTML 函数拿到返回值后的处理源码解析

    目录 引言 parseStartTag函数返回值 handleStartTag源码 tagName 及unarySlash 调用parser钩子函数 引言 继上篇文章: parseHTML 函数源码解析 var startTagMatch = parseStartTag(); if (startTagMatch) { handleStartTag(startTagMatch); if (shouldIgnoreFirstNewline(startTagMatch.tagName, html))

  • vue parseHTML函数源码解析start钩子函数

    目录 正文 platformGetTagNamespace 源码 isForbiddenTag 函数 addIfCondition是什么 processIfConditions 源码 正文 接上章节:parseHTML 函数源码解析 AST 预备知识 现在我们就可以愉快的进入到Vue start钩子函数源码部分了. start: function start(tag, attrs, unary) { // check namespace. // inherit parent ns if ther

  • Vue 2源码解析ParseHTML函数HTML模板

    ParseHTML函数 - HTML 模板解析 之前在解析 parse 函数时,我们知道整个 解析 template 模板并生成 ast 对象 的过程都发生在这个函数的执行过程中. 但是 parse 函数内部本身只定义了一些标签.指令的处理方法和警告函数,并且在传递给 parseHTML 函数的参数中定义了四个处理方法. 最终是通过调用 parseHTML 来解析 template 模板 整个解析过程,其实就是 通过一系列正则表达式来匹配 template 模板字符串,并截取该部分匹配内容并重新

  • vue parseHTML 函数源码解析

    目录 正文 函数开头定义的一些常量和变量 while 循环 textEnd ===0 parseStartTag 函数解析开始标签 总结: 正文 接上篇: Vue编译器源码分析AST 抽象语法树 function parseHTML(html, options) { var stack = []; var expectHTML = options.expectHTML; var isUnaryTag$$1 = options.isUnaryTag || no; var canBeLeftOpen

  • Vue 2源码解析HTMLParserOptions.start函数方法

    目录 HTMLParserOptions.start() 处理后的 input ast element HTMLParserOptions.start() 用来解析标签的开始部分(匹配到标签开始部分时调用),主要区分标签类型.解析标签指令配置与动态绑定参数等等. let root let currentParent function start(tag, attrs, unary, start, end) { const ns = (currentParent && currentPare

  • vue parseHTML源码解析hars end comment钩子函数

    目录 引言 chars源码: parseText end 源码: 引言 接上文  parseHTML 函数源码解析(六) start钩子函数 接下来我们主要讲解当解析器遇到一个文本节点时会如何为文本节点创建元素描述对象,又会如何对文本节点做哪些特殊的处理. parseHTML(template, { chars: function(){ //... }, //... }) chars源码: chars: function chars(text) { if (!currentParent) { {

  • 详解vue mint-ui源码解析之loadmore组件

    本文介绍了vue mint-ui源码解析之loadmore组件,分享给大家,具体如下: 接入 官方接入文档mint-ui loadmore文档 接入使用Example html <div id="app"> <mt-loadmore :top-method="loadTop" :bottom-method="loadBottom" :bottom-all-loaded="allLoaded" :max-dis

  • 源码解析ios开发SDWebImage方法

    目录 引言 源码解析 字典操作 看一下调用下载函数前的实例化过程 快速查找缓存的方法回调 开始进入查找函数 总结一下函数调用 1.先调用 2.设置图片 引言 在着手写第二篇的时候,发现这个SDWebimage确实吧NSOperation用的太美了.确实可能帮你理解NSOperation和NSOperationQueue,当然还有Block的队列.还有一个GCD. 各位看官在看的时候可以着重的看看他的operatinQueue的队列.看看是怎么添加到队列的以及是怎么移除队列.在后面的文章就会提到他

  • jstorm源码解析之bolt异常处理方法

    问题 用过storm或者jstorm的都知道,如果在bolt代码中发生了没被catch住的异常,所在worker进程会退出.本文就从源码角度分析一下具体设计,其实并不是"有异常然后进程崩了"这么简单. 实质 我们先看BasicBoltExecutor的源码: public void execute(Tuple input) { _collector.setContext(input); try { _bolt.execute(input, _collector); _collector

  • Vue AST源码解析第一篇

    讲完了数据劫持原理和一堆初始化,现在是DOM相关的代码了. 上一节是从这个函数开始的: // Line-3924 Vue.prototype._init = function(options) { // 大量初始化 // ... // Go! if (vm.$options.el) { vm.$mount(vm.$options.el); } }; 弄完data属性的数据绑定后,开始处理el属性,也就是挂载的DOM节点,这里的vm.$options.el也就是传进去的'#app'字符串. 有一个

  • Java源码解析HashMap的keySet()方法

    HashMap的keySet()方法比较简单,作用是获取HashMap中的key的集合.虽然这个方法十分简单,似乎没有什么可供分析的,但真正看了源码,发现自己还是有很多不懂的地方.下面是keySet的代码. public Set<K> keySet() { Set<K> ks = keySet; if (ks == null) { ks = new KeySet(); keySet = ks; } return ks; } 从代码中了解到,第一次调用keySet方法时,keySet

  • 浅谈C++11的std::function源码解析

    目录 1.源码准备 2.std::function简介 3.源码解析 3.1.std::function解析 3.2.std::_Function_handler解析 3.3._Any_data解析 3.4.std::_Function_base解析 4.总结 1.源码准备 本文是基于gcc-4.9.0的源代码进行分析,std::function是C++11才加入标准的,所以低版本的gcc源码是没有std::function的,建议选择4.9.0或更新的版本去学习,不同版本的gcc源码差异应该不

随机推荐