vue深入解析之render function code详解
发布时间 - 2026-01-11 02:23:41 点击率:次前言

最近在深入的学习研究vue,其实vue在使用上入门并没有什么太高的门槛,但前端同学们也不该仅仅停留在使用上。以 vue 设计、编码之优秀,足当抽丝剥茧,扒开它的外壳,深入其原理。让我们一起来刺破 vue 的心脏,下面话不多说了,来一起看看详细的介绍吧。
vue核心执行过程图
vue核心的执行过程主要分为这几个阶段:
1) 编译模板,生成可复用的render function code(这是今天要重点解读的),这一步在vue实例的整个生命周期中只会执行一次甚至零次,因为我们可以在打包的时候可以预编译
2) 生成watcher等核心渲染监听,在整个vue实例的生命过程中持续发生着作用,对view和modal进行双向绑定
3) 虚拟dom的diff比较,当watcher监听到data的变更的时候,就会根据注入新的data执行render function code,生成新的虚拟dom,跟老的虚拟dom(第一次执行的时候可能为空)进行diff比对,不同的部分将写入真实的dom
这几个过程都会以源码解析的方式分篇解读,今天我们重点讲解的是第一部分模板编译中输出的render function code
render function code解析
一、模板编译过程分解
// 生成ast语法树 const ast = parse(template.trim(), options) // 标记静态内容(以免diff的时候需要重复比较) optimize(ast, options) // 生成render function code const code = generate(ast, options)
很遗憾,上诉三步的代码今天都只是点到为止,不需要太努力,就能在网上搜到相关解析的文章,如果实在找不到同时又感兴趣,可以找到vue源码中的下面文件去读:
// 编译入口 src/compiller/index.js // html解析 src/compiller/parser/html-parser.js // src/compiller下的其它文件
换一个姿势读源码,今天我们要读的是generate(ast, options)生成的render function code的具体代码
二、写一个 vue demo
之前有提到过,读源码需要先了解整体的设计思想、架构,上面那个执行过程图在此列;另外,搭建一个demo执行环境进行debug单步调试,也是一个重要手段(特别是你对源码的目录结构不是特别清晰的时候)。为了让生成的render function code更为完整,写一个覆盖面尽量广的 demo :
//template
<div id="app">
<p>普通属性:{{ message }}</p>
<p>{{msg()}}</p>
<p>{{ct}}</p>
<input v-model="message">
<div v-for="item in items">
{{ item.text }}
</div>
<button v-on:click="bindClick">点我抓同伟</button>
</div>
// js
new Vue({
el: '#app',
data: {
message: '以vue的名义',
items: [{
text: '达康书记'
}, {
text: '育良书记'
}]
},
methods: {
bindClick: function() {
this.message = '这就抓同伟去';
},
msg: function() {
return this.message + "这个方法每次都会执行";
}
},
computed: {
ct: function() {
return this.message + "计算属性并不会每次都执行";
}
}
})
render function code 解析
debug 拿到生成的 render function code(当然也可以通过 webpack 的 vue-loader 编译之后的 dist 文件拿到,此处省略1000字)
with(this) {
return _c('div', {
attrs: {
"id": "app"
}
},
[_c('p', [_v("普通属性:" + _s(message))]), _v(" "), _c('p', [_v(_s(msg()))]), _v(" "), _c('p', [_v(_s(ct))]), _v(" "), _c('input', {
directives: [{
name: "model",
rawName: "v-model",
value: (message),
expression: "message"
}],
domProps: {
"value": (message)
},
on: {
"input": function($event) {
if ($event.target.composing) return;
message = $event.target.value
}
}
}), _v(" "), _l((items),
function(item) {
return _c('div', [_v("\n\t\t " + _s(item.text) + "\n\t ")])
}), _v(" "), _c('button', {
on: {
"click": bindClick
}
},
[_v("点我出奇迹抓同伟")])], 2)
}
甭看这段代码有点怪,但是如果告诉你,这段代码,注入 data 执行,生成的就是传得玄乎其玄的虚拟 dom 树,然后再来一本正经的解(cai)读(ce)一下,你又会觉得这段代码其实没有这么晦涩难懂。ok,结合 demo
来看看,模板相关指令都被解析成什么了:
1) {{messge}} 解析成了 _s(message) ,果断认为这个 _s 就是 toString
2) {{msg()}} method 解析成了 _s(msg()) ,可见每一次 render, msg 方法都会被执行一遍(即使最终没有被反应到真实 dom 上),这就是计算属性存在的意义
3) {{ct}} 计算属性依然被解析成了 _s(ct) ,虽然计算属性可以称之为属性,但是形式上毕竟还是方法,是不是觉得比较奇怪?其实 watcher 除了监听组件,还会监听计算属性依赖的属性,一旦属性发生变更,就会执行计算属性方法,并将执行结果赋值给实例作用域下与计算属性方法名相同的属性,这就是直接使用 _s(ct) 而不是 _s(ct()) 就能正确引用计算属性值的原因,计算属性快就快在了这里
4) v-for="item in items" 被解析成了
_l((items),
function(item) {
return _c('div', [_v("\n\t\t " + _s(item.text) + "\n\t ")])
})
可见 _l 跟 for-each 很类似
5) 至于 v-on:click 则解析成了
_c('button', {
on: {
"click": bindClick
}
}
6) 再来看看 _c, c->create->createNode, 假设这个方法就是创建虚拟节点,回头看上述代码,是不是挺有道理,_c 创建根节点,传入的子节点同样需要这个方法创建。找找源码验证下 src/core/vdom/vnode.js,以下中文注释是我加的
constructor (
tag?: string, //标签名
data?: VNodeData, //属性数据,事件监听等
children?: ?Array<VNode>, //子节点
text?: string,
elm?: Node,
context?: Component,
componentOptions?: VNodeComponentOptions
) {
...
}
至此,也算是自圆其说了
总结
以上就是这篇文章的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对的支持。
# vue
# render
# function
# 简单学习5种处理Vue.js异常的方法
# vue使用技巧及vue项目中遇到的问题
# Vue全局loading及错误提示的思路与实现
# vue新手入门出现function () { [native 
# 成了
# 这段
# 的是
# 就会
# 就能
# 这就是
# 再来
# 这几个
# 这是
# 有什么
# 抽丝剥茧
# 在此
# 不需要
# 说了
# 点到为止
# 找不到
# 还会
# 自圆其说
# 不多
# 告诉你
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
Python文件流缓冲机制_IO性能解析【教程】
Android Socket接口实现即时通讯实例代码
🚀拖拽式CMS建站能否实现高效与个性化并存?
如何快速生成高效建站系统源代码?
Laravel怎么创建控制器Controller_Laravel路由绑定与控制器逻辑编写【指南】
敲碗10年!Mac系列传将迎来「触控与联网」双革新
Laravel如何使用.env文件管理环境变量?(最佳实践)
jquery插件bootstrapValidator表单验证详解
HTML 中如何正确使用模板变量为元素的 name 属性赋值
如何快速搭建二级域名独立网站?
Python文件操作最佳实践_稳定性说明【指导】
Laravel Eloquent关联是什么_Laravel模型一对一与一对多关系精讲
图片制作网站免费软件,有没有免费的网站或软件可以将图片批量转为A4大小的pdf?
Laravel如何处理文件下载请求?(Response示例)
如何实现javascript表单验证_正则表达式有哪些实用技巧
如何快速完成中国万网建站详细流程?
制作网站软件推荐手机版,如何制作属于自己的手机网站app应用?
rsync同步时出现rsync: failed to set times on “xxxx”: Operation not permitted
javascript中数组(Array)对象和字符串(String)对象的常用方法总结
如何为不同团队 ID 动态生成多个独立按钮
Laravel如何实现邮箱地址验证功能_Laravel邮件验证流程与配置
如何快速重置建站主机并恢复默认配置?
WEB开发之注册页面验证码倒计时代码的实现
高端建站三要素:定制模板、企业官网与响应式设计优化
如何在景安云服务器上绑定域名并配置虚拟主机?
厦门模型网站设计制作公司,厦门航空飞机模型掉色怎么办?
如何用景安虚拟主机手机版绑定域名建站?
瓜子二手车官方网站在线入口 瓜子二手车网页版官网通道入口
微信小程序 五星评分(包括半颗星评分)实例代码
Win11怎么设置默认图片查看器_Windows11照片应用关联设置
手机软键盘弹出时影响布局的解决方法
用v-html解决Vue.js渲染中html标签不被解析的问题
成都品牌网站制作公司,成都营业执照年报网上怎么办理?
JS中使用new Date(str)创建时间对象不兼容firefox和ie的解决方法(两种)
海南网站制作公司有哪些,海口网是哪家的?
利用 Google AI 进行 YouTube 视频 SEO 描述优化
Python面向对象测试方法_mock解析【教程】
如何用IIS7快速搭建并优化网站站点?
猎豹浏览器开发者工具怎么打开 猎豹浏览器F12调试工具使用【前端必备】
如何用西部建站助手快速创建专业网站?
西安市网站制作公司,哪个相亲网站比较好?西安比较好的相亲网站?
晋江文学城电脑版官网 晋江文学城网页版直接进入
如何挑选优质建站一级代理提升网站排名?
Linux系统命令中screen命令详解
如何快速查询域名建站关键信息?
如何在HTML表单中获取用户输入并结合JavaScript动态控制复利计算循环
Laravel如何使用集合(Collections)进行数据处理_Laravel Collection常用方法与技巧
网站页面设计需要考虑到这些问题
Laravel用户密码怎么加密_Laravel Hash门面使用教程
Laravel怎么实现前端Toast弹窗提示_Laravel Session闪存数据Flash传递给前端【方法】

