# react-visual-edit-vite
**Repository Path**: ai-tools_4/react-visual-edit-vite
## Basic Information
- **Project Name**: react-visual-edit-vite
- **Description**: No description available
- **Primary Language**: Unknown
- **License**: MIT
- **Default Branch**: main
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2026-02-26
- **Last Updated**: 2026-02-26
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
#### [English](./README.en.md) | 中文
# Visual Edit - 可视化编辑
## 什么是 Visual Edit - 可视化编辑?
基于 Babel AST 转换的 React 可视化编辑器,支持在浏览器中直接编辑组件样式和文本,并将修改回写到源代码。
## Visual Edit有什么用?
在大模型能力不断爆发的今天,很多人(包括非程序员)已经开始使用 AI 来制作自己的 Web App,但是不是每一次 AI 的生成都能够符合我们的预期,甚至只是想修改字体的一个颜色都需要 AI 再 re-generate 一遍,这个时候明明只需要改变一个样式代码就可以了。所以在可视化编辑的加持下,将此功能用来做为 AI 生成 Web App 的工程样板文件中的能力之一,这样 AI 更具这个具有可视化编辑的工程样板生成的代码之后,只需要切换编辑模式,就可以轻松的修改页面的样式(背景色、字体大小等等),极大程度节约了 token 的消耗,而且所见即所得,能够精准控制。
## 说明
此仓库的代码只是一个技术方案示例。
## 特点
- **可视化编辑** - 直接在浏览器中编辑组件样式和文本
- **实时预览** - 修改即刻反映在界面上
- **内联样式** - 样式以 `style={{ ... }}` 形式写入源码
- **代码回写** - 保存后自动更新源代码文件
- **热模块替换** - 无需刷新页面
- **动态内容保护** - 包含 state 的元素会被标记为不可编辑
## 技术方案
### 核心原理
1. **编译时注入** - Vite 插件在 transform 阶段通过 Babel 解析 JSX,为每个元素注入唯一标识符 `data-vid`,同时记录 VID 到源码位置的映射关系
2. **AST 路径定位** - 使用 AST 路径(如 `body.4.body.body.1.argument`)而非行号定位元素,确保代码格式化后仍能准确找到目标节点
3. **运行时编辑** - 浏览器中通过 `data-vid` 识别可编辑元素,样式修改直接操作 DOM 实现实时预览
4. **后端 AST 回写** - 保存时后端根据 VID 查找映射,重新解析源文件为 AST,定位目标节点后更新 `style` 属性,最后生成新代码写入文件
5. **热更新同步** - 文件写入后触发 Vite HMR,页面无刷新更新
### 整体流程图
```
┌─────────────────────────────────────────────────────────────────┐
│ 编译时 (Vite 插件) │
├─────────────────────────────────────────────────────────────────┤
│ JSX 源码 │
│
Hello
│
│ ↓ │
│ Babel AST 解析 + 遍历 │
│ ↓ │
│ 注入 data-vid 属性 + 检测动态内容 │
│ ↓ │
│ Hello
│
│ │
│ 同时记录 VID → 源码位置映射 (vidMap) │
└─────────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────────┐
│ 运行时 (浏览器) │
├─────────────────────────────────────────────────────────────────┤
│ 用户点击元素 │
│ ↓ │
│ 获取 data-vid → 显示编辑面板 │
│ ↓ │
│ 用户修改样式 → 实时预览 (直接修改 el.style) │
│ ↓ │
│ 点击保存 → 发送请求到 /__visual_edit │
└─────────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────────┐
│ 后端处理 (Vite 中间件) │
├─────────────────────────────────────────────────────────────────┤
│ 接收请求 { vid, styles, newText } │
│ ↓ │
│ 从 vidMap 获取文件路径和 AST 路径 │
│ ↓ │
│ 读取源文件 → Babel 解析 → 定位 JSX 节点 │
│ ↓ │
│ 更新 style 属性 (AST 操作) │
│ ↓ │
│ 生成新代码 → 写入文件 │
│ ↓ │
│ 触发 HMR 热更新 │
└─────────────────────────────────────────────────────────────────┘
```
## 快速开始
```bash
# 安装依赖
npm install
# 启动开发服务器
npm run dev
```
访问 http://localhost:5173
## 项目结构
```
demo-babel/
├── src/
│ ├── plugins/ # Vite 插件 (编译时 + 后端)
│ │ ├── index.ts # 插件主入口
│ │ └── utils/
│ │ ├── ast.ts # AST 操作工具
│ │ └── types.ts # 类型定义
│ ├── utils/
│ │ └── overlay/ # 前端编辑界面
│ │ ├── index.ts # 导出入口
│ │ ├── domElements.ts # UI 元素创建
│ │ └── visualEditOverlay.ts # 交互逻辑
│ ├── App.tsx # 示例应用
│ ├── main.tsx # 应用入口
│ └── index.css # 全局样式
├── vite.config.ts # Vite 配置
└── package.json
```
---
## 核心模块详解
### 1. Vite 插件 (`plugins/index.ts`)
插件在 Vite 的 `transform` 钩子中处理 JSX 文件:
```typescript
// 主要功能:
// 1. 为每个 JSX 元素注入 data-vid 属性
// 2. 检测动态内容,标记 data-has-state
// 3. 建立 VID → 源码位置的映射
// 4. 提供 /__visual_edit API 端点处理编辑请求
```
**VID 格式**: `文件名:元素名:索引`,例如 `App.tsx:h1:0`
**VID 映射表结构**:
```typescript
interface VidMapEntry {
file: string; // 源文件路径
astPath: string; // AST 导航路径
elementName: string; // 元素名称
classLiteralStart: number;
classLiteralEnd: number;
}
```
**动态内容检测**:
```typescript
// 检测 JSX children 是否包含表达式
// → data-has-state="true"
for (const child of jsxElement.children) {
if (t.isJSXExpressionContainer(child)) {
hasDynamicContent = true;
}
}
```
### 2. AST 操作 (`plugins/utils/ast.ts`)
提供精确的源码修改能力:
```typescript
// 核心函数:
// 生成 AST 路径(编译时)
generateASTPath(path) → "body.4.body.body.1.argument.children.3"
// 根据路径定位节点(运行时)
findNodeByPath(ast, pathString) → JSXElement
// 更新代码
updateCodeWithAST(code, astPath, {
newClassName?: string,
newText?: string,
newStyles?: StyleConfig // 内联样式
})
```
**样式更新逻辑**:
```typescript
// 更新或创建 style 属性
// 如果已有 style={{ ... }},会合并样式
// 生成结果示例:
// style={{ color: "#ff0000", fontSize: "18px" }}
```
### 3. 前端编辑界面 (`utils/overlay/`)
**domElements.ts** - UI 元素工厂:
```typescript
createHighlightBox() // 高亮框
createFileLabel() // 元素名称标签
createToggleButton() // 编辑模式切换按钮
createStylePanel() // 右侧抽屉面板
showToast() // 提示信息
```
**visualEditOverlay.ts** - 交互逻辑:
```typescript
// 状态管理
let enabled = false;
let currentEditingElement: HTMLElement | null = null;
// 核心函数
highlight(el) // 高亮元素
enterEditMode(el) // 进入编辑
exitEditMode() // 退出编辑
saveStyles() // 保存到后端
```
---
## 数据流
### 编辑保存流程
```
用户点击保存
↓
收集数据: { vid, styles, newText }
↓
POST /__visual_edit
↓
后端解析 vid → 获取 VidMapEntry
↓
读取源文件 → Babel 解析为 AST
↓
findNodeByPath() 定位 JSX 节点
↓
updateStyleAttribute() 更新 style 属性
↓
generate() 生成新代码
↓
写入文件 → 触发 HMR
```
### 请求/响应格式
**请求体**:
```typescript
interface EditRequest {
vid: string;
currentClassName?: string;
newText?: string;
styles?: {
color?: string;
backgroundColor?: string;
fontSize?: string;
fontWeight?: string;
};
}
```
**响应**:
```json
{ "ok": true }
```
---
## 技术栈
| 类别 | 技术 |
| -------- | ---------------- |
| UI 框架 | React 19 |
| 构建工具 | Vite 7 |
| AST 解析 | @babel/parser |
| AST 遍历 | @babel/traverse |
| AST 生成 | @babel/generator |
| 类型系统 | TypeScript |
| 样式 | Tailwind CSS 4 |
---
## 注意事项
1. **仅开发模式** - 编辑功能只在 `npm run dev` 时可用
2. **版本控制** - 修改会直接写入源文件,建议使用 Git
3. **动态内容** - 包含 `{state}` 表达式的元素不可编辑
4. **文本元素** - 仅支持 p, span, button, h1-h6, a, label, div 等文本元素
---
## 许可证
MIT