You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React中拦截console.log替换为自定义函数(结合eval()开发Codepen替代工具)

在React中拦截console.log并实现自定义容器输出(适配eval场景)

要实现类似Codepen的代码运行器,核心是重写console相关方法,并确保eval执行的代码能调用到自定义的输出逻辑,以下是具体实现方案:

核心思路

  1. 在React组件中维护输出消息的状态,用于渲染到自定义div容器
  2. 重写全局console的方法(或在代码执行上下文注入自定义console),将原本的控制台输出转为组件内的状态更新
  3. 处理代码执行时的错误,统一输出到自定义容器

完整实现代码

import { useState, useEffect } from 'react';

function CodePlayground() {
  const [outputMessages, setOutputMessages] = useState([]);
  const [codeInput, setCodeInput] = useState('console.log("Hello from playground!");');

  // 保存原生console方法,防止全局污染后无法恢复
  const originalConsole = {
    log: console.log,
    error: console.error,
    warn: console.warn,
    info: console.info
  };

  // 自定义日志处理函数
  const handleLog = (type, ...args) => {
    // 将任意参数转为可展示的字符串格式
    const formattedMsg = args.map(arg => {
      if (typeof arg === 'object') return JSON.stringify(arg, null, 2);
      return String(arg);
    }).join(' ');

    setOutputMessages(prev => [...prev, { type, message: formattedMsg }]);
    // 可选:保留原生控制台输出,方便调试
    originalConsole[type](...args);
  };

  useEffect(() => {
    // 重写全局console方法
    console.log = (...args) => handleLog('log', ...args);
    console.error = (...args) => handleLog('error', ...args);
    console.warn = (...args) => handleLog('warn', ...args);
    console.info = (...args) => handleLog('info', ...args);

    // 组件卸载时恢复原生console
    return () => {
      Object.assign(console, originalConsole);
    };
  }, []);

  // 执行用户输入的代码
  const runCode = () => {
    setOutputMessages([]);
    try {
      // eval会直接使用全局已重写的console
      eval(codeInput);
    } catch (err) {
      // 捕获代码执行错误并输出
      handleLog('error', `Execution Error: ${err.message}`);
    }
  };

  return (
    <div style={{ padding: '20px', maxWidth: '800px', margin: '0 auto' }}>
      <textarea
        value={codeInput}
        onChange={(e) => setCodeInput(e.target.value)}
        rows={12}
        style={{ width: '100%', padding: '12px', border: '1px solid #ddd', borderRadius: '4px', fontSize: '14px' }}
        placeholder="输入代码,比如console.log('测试输出');"
      />
      <button
        onClick={runCode}
        style={{ marginTop: '10px', padding: '10px 20px', backgroundColor: '#007bff', color: 'white', border: 'none', borderRadius: '4px', cursor: 'pointer' }}
      >
        运行代码
      </button>
      <div style={{ marginTop: '20px', border: '1px solid #ddd', borderRadius: '4px', padding: '15px', backgroundColor: '#f8f9fa' }}>
        <h4 style={{ margin: '0 0 10px 0', color: '#333' }}>输出结果:</h4>
        {outputMessages.length === 0 ? (
          <p style={{ color: '#666' }}>点击运行代码查看输出</p>
        ) : (
          outputMessages.map((msg, idx) => {
            const textColor = {
              error: '#dc3545',
              warn: '#ffc107',
              info: '#17a2b8',
              log: '#28a745'
            }[msg.type];
            return (
              <div key={idx} style={{ marginBottom: '8px', color: textColor }}>
                <span style={{ fontWeight: 'bold' }}>{msg.type.toUpperCase()}:</span> {msg.message}
              </div>
            );
          })
        )}
      </div>
    </div>
  );
}

export default CodePlayground;

关键细节说明

1. 避免全局console污染

组件挂载时重写全局console,卸载时通过保存的originalConsole恢复,防止影响其他组件或应用的正常日志输出。

2. 参数格式化处理

针对对象、数组等复杂类型,使用JSON.stringify转为格式化后的字符串,确保在div容器中能正常展示。

3. 错误捕获

用try-catch包裹eval执行过程,将代码语法错误、运行时错误统一输出到自定义容器,提升用户体验。

4. 更安全的替代eval方案

如果不想污染全局console,可以使用new Function手动注入自定义console上下文,实现隔离执行:

const runCode = () => {
  setOutputMessages([]);
  try {
    // 创建自定义console,仅用于当前代码执行
    const customConsole = {
      log: (...args) => handleLog('log', ...args),
      error: (...args) => handleLog('error', ...args),
      warn: (...args) => handleLog('warn', ...args),
      info: (...args) => handleLog('info', ...args)
    };
    // 用new Function替代eval,传入自定义console作为参数
    const executeCode = new Function('console', codeInput);
    executeCode(customConsole);
  } catch (err) {
    handleLog('error', `Execution Error: ${err.message}`);
  }
};

这种方式更适合多实例场景,不会影响全局环境的console使用。

内容的提问来源于stack exchange,提问作者Rajat Sandeep

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 21:07:23