在Mini-React中实现JSX支持:从环境搭建到组件化实践

105 阅读3分钟

在Mini-React中实现JSX支持:从环境搭建到组件化实践


一、配置JSX开发环境

1. 初始化Vite项目 通过以下命令快速搭建支持JSX的现代前端开发环境:

pnpm create vite
# 项目名:vite-runner
# 框架选择:Vanilla(纯JS)
# 语言选择:JavaScript

这一步生成的基础项目已内置JSX编译能力,无需额外配置。


2. 迁移核心代码 将原有Mini-React代码整合到新项目中:

  • 文件结构调整

    • 将原App.js重命名为App.jsx
    • 复制core文件夹(包含自定义的React.js核心逻辑)
    • 更新main.js入口文件
  • 修改HTML入口

    <!-- index.html -->
    <div id="root"></div>
    <script type="module" src="/main.js"></script>
    

    确保入口文件路径与项目结构匹配。


3. 验证JSX转换 运行以下命令启动开发服务器:

pnpm install && pnpm dev

观察控制台输出,可以看到:

  • JSX语法已被正确转换为React.createElement调用
  • 自定义的createTextNode方法被触发

二、代码改造与效果验证

1. 改造App组件 将原有元素创建方式改为JSX语法:

// App.jsx
import React from './core/React.js';
​
// 写法1:通过函数返回JSX
function AppOne() {
  return <div id="xxx">aaa-bbbb</div>
}
​
// 写法2:直接声明JSX常量
const App = <div>aaa-bbbb</div>console.log("AppOne:", AppOne);  // 观察函数组件形态
console.log("App:", App);        // 查看转换后的对象结构export default App;

通过控制台输出可见,两种写法最终都会转换为包含typeprops的虚拟DOM对象。


2. React核心逻辑core/React.js中实现的简易渲染逻辑:

function createTextNode(text) {
    return {
        type: "TEXT_ELEMENT",
        props: {
            nodeValue: text,
            children: []
        }
    }
}
​
​
function createElement(type, props, ...children) {
    return {
        type,
        props: {
            ...props,
            children: children.map(child => {return typeof child === "string"? createTextNode(child) : child})
        }
    }
}
​
function render(el, container) {
    // 1. 判断元素类型是文本还是其他类型, 如果是文本类型则创建文本节点,否则创建元素节点
    const dom = el.type === "TEXT_ELEMENT" ? document.createTextNode("") : document.createElement(el.type);
​
    // 2.设置元素的属性值为 el.props 中的属性
    Object.keys(el.props).forEach((key) => {
        if (key !== "children") {
            dom[key] = el.props[key];
        }
    });
​
    // 递归的处理子元素
    const children = el.props.children
    children.forEach((child) => {
        render(child, dom);
    });
​
    // 3. 将创建的元素节点添加到指定的容器中
    container.appendChild(dom);
}
​
const React = {
    render,
    createElement,
}
​
export default React

这段代码实现了JSX到虚拟DOM的转换基础能力。


三、当前遗留问题

组件化支持限制

// 期望的组件化写法(暂不可用)
ReactDOM.createRoot(document.querySelector("#root")).render(<App/>)

原因分析: 当前React.js未实现函数组件处理逻辑,无法解析<App/>形式的组件调用。

现象说明

  • 直接使用<App/>会导致渲染异常
  • 必须导出具体的JSX元素(如export default <div>...</div>

四、总结

本文记录了为自研Mini-React框架添加JSX支持的完整过程:通过Vite搭建开发环境,验证JSX编译机制,改造现有组件代码,并分析当前组件化支持的局限。核心收获包括:1)理解JSX本质是React.createElement的语法糖;2)掌握虚拟DOM对象的结构特性;3)明确函数组件支持需要扩展渲染逻辑。目前暂不支持<Component/>语法的问题为后续学习指明了方向,为深入理解React组件化原理奠定了基础。