You need to enable JavaScript to run this app. 如何在Angular中通过HTTP请求获取可使用的Javascript类以实现EditorJS自定义工具
优惠活动
大模型
产品
解决方案
定价
更多

如何在Angular中通过HTTP请求获取可使用的Javascript类以实现EditorJS自定义工具

可行落地方案整理

方案1:隔离沙箱执行(平衡灵活性与安全性)

直接用全局eval风险极高,换成new Function()配合上下文白名单的隔离方案,严格限制动态代码可访问的对象范围,杜绝访问window、cookie、localStorage等敏感资源:

// 从接口拉取工具类的纯代码文本
const toolCode = await this.http.get('/api/custom-tools/[工具标识]', {responseType: 'text'}).toPromise();
// 构造沙箱,仅暴露允许动态工具调用的API
const sandbox = {
  document: {
    createElement: (tag) => {
      // 额外安全校验,禁止创建script等危险标签
      if (['script', 'iframe'].includes(tag.toLowerCase())) throw new Error('非法标签调用');
      return document.createElement(tag);
    }
  },
  EditorJS: window.EditorJS
  // 其他你允许开放的工具类、公共方法均可在此处添加
};
// 用Function构造器执行代码,作用域绑定到沙箱
const getTool = new Function(...Object.keys(sandbox), `return ${toolCode}`);
const CustomBlockTool = getTool(...Object.values(sandbox));
// 直接将CustomBlockTool加入EditorJS的tools配置即可正常使用

此方案可支持完全自定义的工具逻辑,同时把风险控制在可接受范围。

方案2:配置化通用工具(零安全风险,优先推荐)

如果自定义区块的差异仅在HTML结构、样式、输入项、保存字段等可结构化描述的维度,完全不需要传递JS类,前端提前实现一个通用动态工具类,后端仅返回JSON格式的配置即可,零动态代码执行风险:
前端通用工具类示例:

class CommonCustomTool {
  constructor({config}) {
    // config为后端返回的区块配置
    this.config = config;
  }
  render() {
    const wrapper = document.createElement('div');
    wrapper.innerHTML = this.config.template;
    wrapper.style.cssText = this.config.wrapperStyle;
    // 按配置生成输入控件
    this.config.inputs.forEach(inputCfg => {
      const input = document.createElement(inputCfg.type === 'longtext' ? 'textarea' : 'input');
      input.name = inputCfg.field;
      input.placeholder = inputCfg.placeholder;
      wrapper.appendChild(input);
    });
    return wrapper;
  }
  save(blockContent) {
    const result = {};
    this.config.saveFields.forEach(field => {
      result[field] = blockContent.querySelector(`[name="${field}"]`).value;
    });
    return result;
  }
}

后端返回的配置示例:

{
  "toolKey": "product_banner",
  "toolConfig": {
    "wrapperStyle": "padding: 12px; border: 1px solid #f0f0f0; border-radius: 4px;",
    "template": "<h4>产品广告横幅</h4>",
    "inputs": [
      {"field": "title", "type": "text", "placeholder": "输入广告标题"},
      {"field": "img_url", "type": "text", "placeholder": "输入图片地址"},
      {"field": "link", "type": "text", "placeholder": "输入跳转链接"}
    ],
    "saveFields": ["title", "img_url", "link"]
  }
}

Angular侧拉取到配置后,将CommonCustomTool绑定对应配置加入EditorJS的工具列表即可,90%以上的自定义区块场景都可以用这种方案实现,完全没有安全隐患。

方案3:UMD模块动态加载(适合复杂逻辑场景)

如果自定义工具的逻辑非常复杂,配置化无法覆盖,可将每个自定义工具提前打包成独立的UMD模块,后端返回模块的静态资源地址,Angular侧用import()动态加载模块,拿到导出的工具类直接使用。这是Angular官方支持的动态加载方案,安全可控,你可以提前对所有上传的自定义工具模块做静态安全扫描,过滤恶意代码。

注意事项

无论用哪种方案,前后端都需要对所有动态返回的内容做XSS过滤,禁止注入恶意脚本。


内容的提问来源于stack exchange,提问作者Tamás Hájor

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.15 12:36:08