终于搞懂了!原来 Vue 3 的 generate 是这样生成 render 函数的

  • 终于搞懂了!原来 Vue 3 的 generate 是这样生成 render 函数的已关闭评论
  • 79 次浏览
  • A+
所属分类:Web前端
摘要

在之前的 面试官:来说说vue3是怎么处理内置的v-for、v-model等指令? 文章中讲了transform阶段处理完v-for、v-model等指令后,会生成一棵javascript AST抽象语法树。这篇文章我们来接着讲generate阶段是如何根据这棵javascript AST抽象语法树生成render函数字符串的,本文中使用的vue版本为3.4.19。


前言

在之前的 面试官:来说说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函数中使用了两个函数:openBlockcreateElementBlock。在之前的 vue3早已具备抛弃虚拟DOM的能力了文章中我们已经讲过了这两个函数:

  • openBlock的作用为初始化一个全局变量currentBlock数组,用于收集dom树中的所有动态节点。

  • createElementBlock的作用为生成根节点p标签的虚拟DOM,然后将收集到的动态节点数组currentBlock塞到根节点p标签的dynamicChildren属性上。

render函数的生成其实很简单,经过transform阶段处理后会生成一棵javascript AST抽象语法树,这棵树的结构和要生成的render函数结构是一模一样的。所以在generate函数中只需要递归遍历这棵树,进行字符串拼接就可以生成render函数啦!

关注