Vue模板编译

news/2024/11/9 3:10:11/

Vue模板编译

Vue生命周期中,在初始化阶段各项工作做完之后调用了vm.$mount方法,该方法的调用标志着初始化阶段的结束和进入下一个阶段,从官方文档给出的生命周期流程图中可以看到,下一个阶段就进入了模板编译阶段(created和beforeMounted之间的阶段),该阶段所做的主要工作是获取到用户传入的模板内容并将其编译成渲染函数生成模板字符串。然后将这些模板字符串转换成内存中的DOM。
在这里插入图片描述

一、Vue 编译原理这块的整体逻辑主要分三个部分:

1.将模板字符串转换成element AST(抽象语法树)(解析器parser)

2.对AST进行静态节点标记,主要用来做虚拟dom的渲染优化(优化器optimizer)

3.使用element AST 生成render函数代码字符串(代码生成器code generator )

在这里插入图片描述
伪代码

// main.js文件
new Vue({el: '#app',templete: `<div>hello world</div>`, //可选render: h => h(App), //渲染函数
}).$mount('#app') //挂载函数Vue.prototype.__init = function (options) {const vm = this;vm.$options = options;initState(vm);if (vm.$options.el) {//$mount 挂载函数vm.$mount(vm.$options.el)}
}Vue.prototype.$mount = function (el) {const vm = this, options = vm.$options;el = document.querySelector(el);vm.$el = el;if (!options.render) {let templete = options.templete;  //是否有templete选项if (!templete && el) {templete = el.outerHTML}//把这个模板变成render函数const render = compileToRenderFunction(templete); //把HTML转化成SAT树options.render = render;}}
解析器AST在线生成
<div class='container' id='root'><p class='name'>{{name}}</p>
</div>

上面一个简单 的模版转换成element AST树形结构后是这样的

{tag: "div"type: 1,staticRoot: false,static: false,plain: true,parent: undefined,attrsList: [{name:'class',value:'container'},{name:'id':value:'root'}],attrsMap: {},children: [{tag: "p"type: 1,staticRoot: false,static: false,plain: true,parent: {tag: "div", ...},attrsList: [{name:'class', value:'name'}],attrsMap: {},children: [{type: 2,text: "{{name}}",static: false,expression: "_s(name)"}]}]
}

我们可以看到上面的dom被解析成了解析器,它的原理主要是两部分内容,一部分是截取字符串,一部分是对截取的字符串做解析。

优化器

优化器的目的就是找出那些静态节点并打上标记,而静态节点指的是DOM不需要发生变化的节点,也就是里面都是静态标签和静态文本。

标记静态节点有两个好处:
  • 一、每次重新渲染的时候不需要为静态节点创建新节点,也就是静态节点的解析器不需要重新创建
  • 二、在虚拟 DOM中patching的过程可以被跳过
优化器的实现原理主要分两步:
  • 一、用递归的方式将静态节点添加static属性,用来标识是不是静态节点
  • 二、标记所有静态根节点(子节点全是静态节点就是静态根节点)
代码生成器

代码生成器的作用是使用element ASTs生成render函数代码字符串(带有__c, v, _s)
使用本文开头举的例子中的模版生成后的AST来生成render后是这样的:

{render: with(this){return _c('div',[_c('p',[_v(_s(name))])])
}
}

生成后的代码字符串中看到了有几个函数调用_c、_v、_s。
_c对应的是createElement,它的作用是创建一个元素。
1.第一个参数是一个HTML标签名
2.第二个参数是元素上使用的属性所对应的数据对象,可选项
3.第三个参数是children
_v的意思是创建一个文本节点。
_s是返回参数中的字符串。

代码生成器的总体逻辑其实就是使用element ASTs去递归,然后拼出这样的_c(‘div’,[_c(‘p’,[_v(_s(name))])]) 字符串。

问题:在模板编译的阶段,是不是就会对每个组件所使用的data或者computed值进行访问,从而创建新的Watcher进行订阅,然后对应的属性的dep就会收集这些watcher,从而实现更新的?

答:不是的,模板编译只是会把模板编译成渲染函数,只有在渲染函数被执行的时候才会对数据进行访问,而渲染函数是在watche实例中执行的,所以渲染函数中所使用到的所有数据,都会被同一个Watcher监听,当这些状态发生变化时,会通知这个Watcher,这个Watcher会触发VirtualDOM对组件进行渲染。一个组件的模板会被编译成一个渲染函数。每个组件有一个Watcher用来监听模板中所使用到的数据、当这些数据发生变化时,通过VirtualDOM进行更新组件的视图


http://www.ppmy.cn/news/1287133.html

相关文章

自定义注解结合Hutool对SpringBoot接口返回数据进行脱敏

首先说到脱敏问题,我相信在座的很多人都需要处理这样的场景,比如前端页面显示的身份证号、地址等敏感信息都需要脱敏处理,而hutool就有这样的一个工具来辅助我们完成对某些字段属性信息的脱敏,hutool没有现成的实现方式,只是借助这个工具帮助我们来具体实现 前言 我们在…

2023.12.28 网络编程

目录 bytes和str类型的互相转换 TCP服务端代码 TCP客户端代码 一直运行服务器代码 一直运行客户端代码 网络编程三要素:ip地址,端口号,协议 端口号 0-65535 ,二的十六次方 TCP/IP协议 传输数据之前要建立连接&#xff0c;通过三次握手建立&#xff1a; 客户端 --> 服务…

【Google】关于Google Analytics埋点及API获取数据

本文是在实际操作中踩到的一些坑&#xff0c;并不是操作手册。具体的还是需要仔细按照官方文档操作。 参考文档&#xff1a;https://developers.google.com/analytics/ 重点看标红的文档即可 普通事件埋点 各端需要跟产品端确定好统一的事件名称和参数&#xff0c;否则数据混…

【MYSQL】MYSQL 的学习教程(七)之 慢 SQL 优化思路

1. 慢 SQL 优化思路 慢查询日志记录慢 SQLexplain 分析 SQL 的执行计划profile 分析执行耗时Optimizer Trace 分析详情确定问题并采用相应的措施 1. 慢查询日志记录慢 SQL 如何定位慢SQL呢&#xff1f; 我们可以通过 慢查询日志 来查看慢 SQL。 ①&#xff1a;开启慢查询日志…

AndroidR集成三方Native服务组件

一、背景 该项目为海外欧盟市场版本,需集成三方IDS安全组件,进程运行时注入iptables指令至链表,检测网络运行状态,并收集异常日志并压缩打包成gz文件,提供给Android上层应用上报云端。 二、分析 1、将提供的组件包集成至系统vendor分区 /vendor/bin/idsLogd/vendor/li…

【C#与Redis】--实践案例--案例 3:使用 Redis 实现排行榜

实现一个基本的排行榜系统通常涉及到对分数进行排序&#xff0c;而 Redis 的 Sorted Set 数据结构非常适合这种用途。以下是一个使用 StackExchange.Redis 库在 C# 中实现排行榜的简单案例&#xff1a; 安装 StackExchange.Redis 库&#xff1a; Install-Package StackExchan…

Springcloud Alibaba使用Canal将Mysql数据实时同步到Redis保证缓存的一致性

目录 1. 背景 2. Windows系统安装canal 3.Mysql准备工作 4. 公共依赖包 5. Redis缓存设计 6. mall-canal-service 1. 背景 canal [kənl] &#xff0c;译意为水道/管道/沟渠&#xff0c;主要用途是基于 MySQL 数据库增量日志解析&#xff0c;提供增量数据订阅和消费。其诞…

ElasticSearch Nested类型全文检索、聚合查询

ElasticSearch Nested类型全文检索、聚合查询 Nested类型全文检索 创建索引 PUT /products1 {"mappings": {"properties": {"fulltext": {"type": "text"},"name": {"type": "text","…