- A+
所属分类:Web前端
前言
在之前的 面试官:来说说vue3是怎么处理内置的v-for、v-model等指令? 文章中讲了transform
阶段处理完v-for、v-model等指令后,会生成一棵javascript AST抽象语法树。这篇文章我们来接着讲generate
阶段是如何根据这棵javascript AST抽象语法树生成render函数字符串的,本文中使用的vue版本为3.4.19
。
看个demo
还是一样的套路,我们通过debug一个demo来搞清楚render函数字符串是如何生成的。demo代码如下:
<template> <p>{{ msg }}</p> </template> <script setup lang="ts"> import { ref } from "vue"; const msg = ref("hello world"); </script>
上面这个demo很简单,使用p标签渲染一个msg响应式变量,变量的值为"hello world"。我们在浏览器中来看看这个demo生成的render函数是什么样的,代码如下:
import { toDisplayString as _toDisplayString, openBlock as _openBlock, createElementBlock as _createElementBlock } from "/node_modules/.vite/deps/vue.js?v=23bfe016"; function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) { return _openBlock(), _createElementBlock( "p", null, _toDisplayString($setup.msg), 1 /* TEXT */ ); }
上面的render函数中使用了两个函数:openBlock
和createElementBlock
。在之前的 vue3早已具备抛弃虚拟DOM的能力了文章中我们已经讲过了这两个函数:
-
openBlock
的作用为初始化一个全局变量currentBlock
数组,用于收集dom树中的所有动态节点。 -
createElementBlock
的作用为生成根节点p标签的虚拟DOM,然后将收集到的动态节点数组currentBlock
塞到根节点p标签的dynamicChildren
属性上。
render函数的生成其实很简单,经过transform
阶段处理后会生成一棵javascript AST抽象语法树
,这棵树的结构和要生成的render函数结构是一模一样的。所以在generate
函数中只需要递归遍历这棵树,进行字符串拼接就可以生成render函数啦!
关注