React Grab 使用文档
📖 项目简介
React Grab 是一个专为前端开发的开发者工具,允许你直接从网站页面上选择 UI 元素,快速获取其代码上下文信息(包括文件名、组件名和 HTML 源码),并将其复制到剪贴板。
核心价值
- 提升 AI 编码效率:为 Trae、Cursor、Claude Code、Copilot 等 AI 编码工具提供精确的元素上下文,使其运行速度提升高达 3 倍
- 精准定位:快速定位 UI 元素对应的源代码位置
- 零配置使用:安装后即可使用,无需复杂配置
工作原理
在浏览器中悬停在任何 UI 元素上,按下快捷键即可复制该元素的上下文信息:
- Mac:
⌘C(Cmd+C) - Windows/Linux:
Ctrl+C(Windows/Linux)
复制的信息格式示例:
js
<a class="ml-auto inline-block text-sm" href="#">
Forgot your password?
</a>
in LoginForm at components/login-form.tsx:46:19🚀 使用方法

1. 启动开发服务器
确保在开发环境(NODE_ENV=development)下运行项目。
2. 选择元素
- 在浏览器中打开你的应用
- 将鼠标悬停在任意 UI 元素上
- 按下
⌘C(Mac) 或Ctrl+C(Windows/Linux)
3. 粘贴到 Trae 编辑器
复制的信息会自动包含:
- 元素的 HTML 源码
- React 组件名称
- 文件路径和行号
直接粘贴到 Trae 的对话框中即可进行精确的代码修改。
🔌 插件系统
通过插件可以扩展 React Grab 的功能,包括:
- 右键菜单操作
- 工具栏菜单项
- 生命周期钩子
- 主题覆盖
注册插件
js
import { registerPlugin } from "react-grab";
registerPlugin({
name: "my-plugin",
hooks: {
onElementSelect: (element) => {
console.log("Selected:", element.tagName);
},
},
});在 React 中使用
jsx
import { registerPlugin, unregisterPlugin } from "react-grab";
useEffect(() => {
registerPlugin({
name: "my-plugin",
actions: [
{
id: "my-action",
label: "My Action",
shortcut: "M",
onAction: (context) => {
console.log("Action on:", context.element);
context.hideContextMenu();
},
},
],
});
return () => unregisterPlugin("my-plugin");
}, []);自定义操作位置
使用 target 字段控制操作显示位置:
js
actions: [
{
id: "inspect",
label: "Inspect",
shortcut: "I",
onAction: (ctx) => console.dir(ctx.element),
// 默认在右键菜单中显示
},
{
id: "toggle-freeze",
label: "Freeze",
target: "toolbar", // 在工具栏下拉菜单中显示
isActive: () => isFrozen,
onAction: () => toggleFreeze(),
},
];🧩 原始 API(Primitives)
使用原始 API 可以完全自定义元素选择器,不依赖 React Grab 的默认 UI。
禁用自动初始化
如果只想使用原始 API 而不显示默认覆盖层:
html
<script>
window.__REACT_GRAB_DISABLED__ = true;
</script>自定义元素选择器示例
tsx
import { useState } from "react";
import {
getElementContext,
freeze,
unfreeze,
openFile,
type ReactGrabElementContext,
} from "react-grab/primitives";
const useElementSelector = (
onSelect: (context: ReactGrabElementContext) => void,
) => {
const [isActive, setIsActive] = useState(false);
const startSelecting = () => {
setIsActive(true);
// 创建高亮覆盖层
const highlightOverlay = document.createElement("div");
Object.assign(highlightOverlay.style, {
position: "fixed",
pointerEvents: "none",
zIndex: "999999",
border: "2px solid #3b82f6",
transition: "all 75ms ease-out",
display: "none",
});
document.body.appendChild(highlightOverlay);
// 鼠标移动处理
const handleMouseMove = ({ clientX, clientY }: MouseEvent) => {
highlightOverlay.style.display = "none";
const target = document.elementFromPoint(clientX, clientY);
if (!target) return;
const { top, left, width, height } = target.getBoundingClientRect();
Object.assign(highlightOverlay.style, {
top: `${top}px`,
left: `${left}px`,
width: `${width}px`,
height: `${height}px`,
display: "block",
});
};
// 点击处理
const handleClick = async ({ clientX, clientY }: MouseEvent) => {
highlightOverlay.style.display = "none";
const target = document.elementFromPoint(clientX, clientY);
teardown();
if (!target) return;
freeze();
onSelect(await getElementContext(target));
unfreeze();
};
const teardown = () => {
document.removeEventListener("mousemove", handleMouseMove);
document.removeEventListener("click", handleClick, true);
highlightOverlay.remove();
setIsActive(false);
};
document.addEventListener("mousemove", handleMouseMove);
document.addEventListener("click", handleClick, true);
};
return { isActive, startSelecting };
};
// 使用示例
const ElementSelector = () => {
const [context, setContext] = useState<ReactGrabElementContext | null>(null);
const selector = useElementSelector(setContext);
return (
<div>
<button onClick={selector.startSelecting} disabled={selector.isActive}>
{selector.isActive ? "Selecting…" : "Select Element"}
</button>
{context && (
<div>
<p>Component: {context.componentName}</p>
<p>Selector: {context.selector}</p>
<pre>{context.stackString}</pre>
<button
onClick={() => {
const frame = context.stack[0];
if (frame?.fileName) openFile(frame.fileName, frame.lineNumber);
}}
>
Open File
</button>
</div>
)}
</div>
);
};🔗 MCP 集成
连接 MCP(Model Context Protocol)以增强 AI 编码工具的集成:
bash
npx -y grab@latest add mcp📝 可用 API
核心导出
| API | 说明 |
|---|---|
registerPlugin(plugin) | 注册插件 |
unregisterPlugin(name) | 注销插件 |
getElementContext(element) | 获取元素的上下文信息 |
freeze() | 冻结当前页面状态 |
unfreeze() | 解除冻结 |
openFile(fileName, lineNumber) | 在编辑器中打开文件 |
元素上下文结构
typescript
interface ReactGrabElementContext {
element: HTMLElement; // DOM 元素
componentName: string; // React 组件名
selector: string; // CSS 选择器
stackString: string; // 调用栈字符串
stack: Array<{
fileName: string; // 文件名
lineNumber: number; // 行号
}>;
hideContextMenu: () => void; // 隐藏右键菜单
}💡 使用场景
1. Trae AI 辅助开发
- 快速向 Trae 提供精确的 UI 元素信息
- 减少手动查找文件的时间
- 提高代码修改的准确性
2. 代码审查
- 快速定位 UI 元素对应的源代码
- 理解组件结构和文件位置
3. 调试和排查
- 识别未知组件的来源
- 追踪 UI 问题的根源
⚠️ 注意事项
- 仅开发环境使用:React Grab 默认只在开发环境(
NODE_ENV=development)下激活 - 生产环境禁用:确保在生产环境中不加载此工具
- 浏览器兼容性:需要现代浏览器支持
📚 相关资源
- GitHub 仓库: https://github.com/aidenybai/react-grab
- 在线演示: https://react-grab.com
- NPM 包: https://npmjs.com/package/react-grab
📄 许可证
MIT License
文档生成日期:2026 年 3 月 19 日
