VUE模版,vue.js模板

  VUE模版,vue.js模板

  本文的初衷是让更多的学习者了解和理解vue模板编译,所以本文主要关注阶段过程,不涉及太多底层代码逻辑。有需要的朋友可以参考一下。

  :

目录

   1.parse解析器截获的规则1.1 1.2截获过程第1.3部分解析器摘要2。优化优化器2.1静态节点2.2静态根节点2.3优化器摘要3。带有生成代码生成器3.1的语法JS思考:

  Html是标签语言,只有JS可以实现判断和循环,而模板有指令,插值,JS表达式,可以实现判断和循环。所以模板不是html,必须转换成某种JS代码。这种编译是如何工作的?

  解析:

  模板编译是将模板编译成渲染函数这个过程大致可以分成三个阶段:的过程

  

1、parse 解析器

  解析器主要是将模板字符串转换成elementsts。

  模板字符串:

  差异

  p{{message}}/p

  /div

  element ASTs

  AST指的是抽象语法树,类似于Vnode,使用JavaScript对象来描述节点的树形表示。

  {

  标签:“div”

  //节点的类型(1标签,2包含文字表达式的文本节点,3普通文本节点或注释节点)

  类型:1,

  //静态根节点

  staticRoot: false,

  //静态节点

  静态:假,

  平原:真的,

  //父节点元素描述对象的引用

  父:未定义,

  //只有当节点类型为1时,才会有attrsList属性,这是一个对象数组,存储原来的html属性名和值。

  属性列表:[],

  //同上,不同的是attrsMap将html属性名和值存储为键值对。

  属性映射:{},

  //存储该节点所有子节点的元素描述对象。

  儿童:[

  {

  标签:“p”

  类型:1,

  staticRoot: false,

  静态:假,

  平原:真的,

  父级:{tag: div ,},

  属性列表:[],

  属性映射:{},

  孩子:[{

  类型:2,

  文本:“{{message}}”,

  静态:假,

  //当节点类型为2时,对象将包含的表达式

  表达式:“_s(消息)”

  }]

  }

  ]

  }

  

1.1 截取的规则

  主要是通过判断模板中html.indexof()的值,来确定要截取标签还是文本.

  截取的过程:

  字符串部分

  ` divp{{message}}p/div

  

1.2 截取过程部分

  第一次截取

  确定模板中html.indexof(“”)的值,该值为零(注释、条件注释、文档类型、开始标记和结束标记中的一个)

  初始标签的常规匹配是成功的。获取当前标记名div,然后截掉匹配成功的 div 部分,得到一个新的字符串p{{message}}/p/div。

  切断开始标签后,它会利用匹配属性的规律性来进行匹配。如果匹配成功,将获得标签的属性列表。如果匹配不成功,标签的属性列表将是一个空数组。

  属性被截断后,再与匹配开始标记结束的正则性进行匹配,得到是否是自结束标记的信息,然后将匹配的字符串截断,得到新的字符串p{{message}}/p/div。

  匹配开始标记以确定当前节点是否有根节点。如果没有,将创建一个元素类型的树节点。如果是,它将被设置为currentParent的子节点,然后当前节点将被推入堆栈。

  /**

  概括为、匹配标签、选择属性和建立层次结构。

  */

  //经过上面的匹配,剩下的字符串部分是:

  ` p{{message}}p/div

  第二次截取

  /**

  同上

  */

  //经过上面的匹配,剩下的字符串部分是:

  ` { { message } }/p/div ` 1

  第三次截取

  确定模板中html.indexof(“”)的值,该值大于或等于零(文本和表达式之一)

  查询最近的“”并匹配它(开始标记、结束标记、注释和条件注释之一)。如果匹配成功,遍历结束;如果不成功,遍历将继续。

  例如:

  A/p=文本部分a b,点击结束标签。

  Ab/p=文本部分A

  ,点击开始标签b。

  /**

  总结,判断类型,截取正文。

  */

  //经过上面的匹配,剩下的字符串部分是:

  `/p/div

  第四次截取

  确定模板中html.indexof(“”)的值,该值为零(注释、条件注释、文档类型、开始标记和结束标记中的一个)

  成品标签正则匹配成功,然后将匹配成功的标签的/p部分截断,得到一个新的string /div。

  当结束标记匹配时,将从堆栈中弹出一个节点“p ”,堆栈中的最后一个节点“div”将被设置为currentParent。

  /**

  总结为,匹配标签,并确定层次结构。

  */

  //经过上面的匹配,剩下的字符串部分是:

  `/div

  第五次拦截

  /**

  同上

  */

  目标

  

1.3 解析器总结

  模板字符串转换成元素ASTs的过程,其实就是不断截取字符串并解析的过程。

  当开始标记匹配时,截取相应的开始标记,定义AST的基本结构,以及属性(tagName)、指令等。对标签进行分析,并将标签推入堆栈。

  要匹配结束标记,需要通过这个结束标记的标记名从后向前匹配堆栈中每个项目的标记名,并删除匹配项目之后的所有项目(弹出堆栈),这样堆栈中的最后一个项目就是父元素。

  在解析阶段,节点会被拉平,没有层级关系。通过观察,可以找到节点树,可以发现最里面的节点已经解析过了,最后解析的往往是父元素,所以我们通过一个栈来记录节点的层次关系。

  自结束标签input/中没有子节点,所以不需要推送到堆栈中。

  

2、optimize 优化器

  优化器主要用于优化生成的AST的静态内容,标记静态节点。对于每次重新渲染,不需要为静态子树创建新的节点,可以跳过虚拟DOM中的补丁过程(即不需要参与二次页面渲染,大大提高了渲染效率)。

  

2.1 静态节点

  遍历AST语法树,找出所有的静态节点并打上标记

  函数是静态的(节点){

  //表达式

  if (node.type===2) {

  返回false

  }

  //文本

  if (node.type===3) {

  返回true

  }

  /**

  1.不能使用动态绑定语法,即标签上不能有以v-、@、开头的属性;

  2.不能使用v-if、v-else和v-for指令;

  3.不能是内置组件,即标签名不能是槽和组件;

  4.标记名必须是平台保留标记,即不能是组件;

  5.当前节点的父节点不能是带有v-for的模板标记;

  6.节点所有属性的键必须是静态节点所独有的。注意:静态节点的键是有限的。

  它只能是type、tag、attrslist、attrsmap、plain、parent、children和attrs中的一个。

  */

  回归!(node.pre (

  !node . has绑定

  !node.if!node.for

  !isbuiltingag(node . tag)

  isPlatformReservedTag(node.tag)

  !isDirectChildOfTemplateFor(节点)

  Object.keys(节点)。每(isStaticKey)

  ))

  }

  

2.2 静态根节点

  经过以上步骤后遍历树,找到静态根节点并标记。

  

2.3 优化器总结

  不使用vue特有语法的节点(v-pre v-once除外)可以称为静态节点。

  静态节点:表示当前节点及其所有子节点都是静态节点。

  静态根节点:指的是一个节点,它本身及其所有的子节点都是静态节点,但父节点是动态节点。

  

3、generate 代码生成器

  代码生成器的作用是通过AST语法树生成一个代码串,代码串被包装成一个渲染函数。执行渲染函数后,可以获得一个vnode。

  

3.1 JS的with语法

  使用,您可以更改{0}中自由变量的搜索方法,并将{0}中的自由变量用作obj的属性。如果找不到匹配的obj属性,就会报错。

  const obj={a: 100,b: 200}

  用(obj)

  console.log(a)

  console.log(b)

  //console.log(c) //将报告一个错误

  }

  代码字符串

  解析由Parse生成的elementsts并将它们拼接成字符串。

  with(this){return _c(div ,_c(p ,[_ v(message)])}

  得到render函数:

  /* *代码串可以通过new Function (code string) */

  const string code=` with(this){ return _ c( div ,_c(p ,[_ v(message)])} ` 1

  const render=新函数(stringCode)

  欲观看不同指令、插值、JS表达式,可使用vue-template转换

  const compiler=require( vue-template-compiler )

  //插值

  const template=` p { { message } }/p ` 1

  const result=compiler.compile(模板)

  console.log(结果.渲染)

  //with(this){return _c(p ,[_v(_s(message))])}

  vue 源代码找到缩写函数的含义

  模板编译后的源代码可以在“vue-template-compiler` [2]包中查看。

  函数installRenderHelpers(目标){

  目标。_c=createElement

  //标记v-once

  目标。_o=马克龙

  //转换为数字类型

  目标。_n=toNumber

  //转换为字符串

  目标。_s=toString

  //渲染v-for

  目标。_l=renderList

  //呈现普通插槽和作用域插槽

  目标。_t=renderSlot

  //通过staticRenderFns呈现静态节点

  目标。_m=renderStatic

  //获取过滤器

  目标。_ f=resolveFilter过滤器

  //检查键盘事件键码

  目标。_k=checkKeyCodes

  目标。_b=bindObjectProps

  //创建文本vnode

  目标。_v=createTextVNode

  //创建一个空的vnode

  目标。_e=createEmptyVNode

  目标。_u=resolveScopedSlots

  目标。_g=bindObjectListeners

  //处理修饰符

  目标。_p=前置修饰符

  }

  综述:

  vue-loader将在开发环境中用于模板编译(预编译)的vue支架中。

  解析过程是截取小段字符串,然后维护一个栈来保存DOM深度。当所有的字符串都被截取时,一个完整的AST将被解析。

  优化过程是递归标记所有节点,表明它们是否是静态节点,然后再次递归标记静态根节点。

  在代码生成阶段,递归生成函数执行的代码字符串,递归过程根据不同的节点类型调用不同的生成方法。

  关于vue模板的编译细节这篇文章到此为止。更多相关vue模板编译内容,请搜索我们之前的文章或者继续浏览下面的相关文章。希望大家以后能多多支持我们!

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: