相信大家对 react 和 vue 两个前端框架已经非常熟悉,vue 的模版指令深入人心,react 的 jsx 又非常灵活,那我们先来看一个问题:可以在 react 中实现 vue 的模版指令吗,比如 v-for?
这是一个非常有意思的话题,前端框架的天然壁垒使得语法上互不兼容,但透过表象看本质我们发现,框架形式变幻莫测,都是受底层设计思想的支配,打破壁垒往往只需要你敢于尝试。
今天我们要探讨的问题其实也不单单是在 react 中实现一个 v-for 这样的模版指令,而是基于模版指令的实现过程,探讨在 react 中开发者能做的预编译优化。
我们知道在 react 中通过一个数组生成一堆平行节点常用的就是在 jsx 中调用 map 方法:
而如果支持类似 v-for 指令(react 中就叫 r-for 吧):
且不说代码量是否更加简单,光是模版指令的语法看起来就十分优雅,我们不妨试一试实现这个需求。
大家对于实现方案应该有了自己的答案,避免不了就是要基于 babel 编译的 AST 来实现,最终以插件的形式引入我们的项目中,编译 r-for 指令。
我们先回顾一下 ast,ast 是抽象语法树,是源代码语法结构的一种抽象表示。代码中的每一个代码节点都会被解析成一个包装对象。比如
const a = 3
这一句简单的代码,被解析成 ast 为:
其中 VariableDeclarator 就是变量包装对象,等号两边的变量名和变量初始值也会被解析成相应的包装对象。了解 ast 之后我们再回顾一下 babel 编译 react 代码的过程:
源代码解析 ast 的 parse 过程在 babel 官网已经给出了流程,分别由 @babel/parser、@babel/traverse、@babel/generator 执行,parser 会把源代码编译成原始的 ast,而我们配置的 presets 和插件就是在第二部分执行,将 原始 ast 进一步编译成最终的 ast。
而关于 babel