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

如何在Component中动态注入后端返回的HTML与script代码

动态注入含script的HTML内容到组件视图的解决方案

浏览器默认使用innerHTML插入HTML时,不会执行其中的<script>标签,所以除了插入HTML结构,还需要单独处理script标签的加载执行逻辑,以下是通用方案和各主流框架的实现示例:

通用实现步骤

  • 先将后端返回的HTML字符串解析为临时DOM结构,提取所有的script标签
  • 将剥离了script标签的HTML内容插入到组件的目标容器中
  • 逐个处理提取到的script标签:如果是外部src引入的script,动态创建script节点插入到文档中;如果是内联script,直接执行内部代码

各主流框架实现示例

Vue 框架实现

结合v-html指令+手动处理script:

<template>
  <div ref="embedContainer" v-html="pureHtml"></div>
</template>

<script setup>
import { ref, watch, onMounted, nextTick } from 'vue'
const embedContainer = ref(null)
const article = ref({
  embed_script: '' // 后端返回的embed_script内容
})
const pureHtml = ref('')

const injectEmbedContent = (content) => {
  // 临时DOM节点解析内容
  const tempDiv = document.createElement('div')
  tempDiv.innerHTML = content
  // 提取所有script标签
  const scripts = tempDiv.querySelectorAll('script')
  // 剥离script后的纯HTML
  pureHtml.value = tempDiv.innerHTML.replace(/<script[^>]*>[\s\S]*?<\/script>/gi, '')

  // 等待HTML渲染完成后处理script
  nextTick(() => {
    scripts.forEach(oldScript => {
      const newScript = document.createElement('script')
      // 复制所有原script属性
      Array.from(oldScript.attributes).forEach(attr => {
        newScript.setAttribute(attr.name, attr.value)
      })
      // 复制内联脚本内容
      if (oldScript.innerHTML) {
        newScript.innerHTML = oldScript.innerHTML
      }
      embedContainer.value.appendChild(newScript)
    })
  })
}

onMounted(() => {
  // 接口请求获取article数据后调用注入方法
  injectEmbedContent(article.value.embed_script)
})
</script>

React 框架实现

结合dangerouslySetInnerHTML+useRef处理:

import { useEffect, useRef } from 'react'

const EmbedComponent = ({ article }) => {
  const containerRef = useRef(null)

  useEffect(() => {
    if (!article?.embed_script || !containerRef.current) return
    const content = article.embed_script
    const tempDiv = document.createElement('div')
    tempDiv.innerHTML = content
    const scripts = tempDiv.querySelectorAll('script')
    // 先插入纯HTML
    containerRef.current.innerHTML = tempDiv.innerHTML.replace(/<script[^>]*>[\s\S]*?<\/script>/gi, '')
    // 处理script标签
    scripts.forEach(oldScript => {
      const newScript = document.createElement('script')
      Array.from(oldScript.attributes).forEach(attr => {
        newScript.setAttribute(attr.name, attr.value)
      })
      if (oldScript.innerHTML) newScript.innerHTML = oldScript.innerHTML
      containerRef.current.appendChild(newScript)
    })
    // 组件卸载时清理内容避免内存泄漏
    return () => {
      if (containerRef.current) {
        containerRef.current.innerHTML = ''
      }
    }
  }, [article])

  return <div ref={containerRef}></div>
}

export default EmbedComponent

Angular 框架实现

结合DomSanitizer处理安全上下文后手动处理script:

import { Component, Input, ElementRef, OnInit, OnDestroy } from '@angular/core';
import { DomSanitizer } from '@angular/platform-browser';

@Component({
  selector: 'app-embed',
  template: '<div [innerHTML]="pureHtml"></div>'
})
export class EmbedComponent implements OnInit, OnDestroy {
  @Input() article: any;
  pureHtml: any;

  constructor(
    private sanitizer: DomSanitizer,
    private el: ElementRef
  ) {}

  ngOnInit(): void {
    if (!this.article?.embed_script) return
    const content = this.article.embed_script
    const tempDiv = document.createElement('div')
    tempDiv.innerHTML = content
    const scripts = tempDiv.querySelectorAll('script')
    // 清理script后消毒HTML
    const rawHtml = tempDiv.innerHTML.replace(/<script[^>]*>[\s\S]*?<\/script>/gi, '')
    this.pureHtml = this.sanitizer.bypassSecurityTrustHtml(rawHtml)

    // 渲染完成后处理script
    setTimeout(() => {
      const container = this.el.nativeElement.querySelector('div')
      scripts.forEach(oldScript => {
        const newScript = document.createElement('script')
        Array.from(oldScript.attributes).forEach(attr => {
          newScript.setAttribute(attr.name, attr.value)
        })
        if (oldScript.innerHTML) newScript.innerHTML = oldScript.innerHTML
        container.appendChild(newScript)
      })
    }, 0)
  }

  ngOnDestroy(): void {
    this.el.nativeElement.innerHTML = ''
  }
}

注意:如果后端返回的内容来源不可信,直接注入script会存在XSS安全风险,请确保仅注入信任的后端返回内容,必要时可对返回的HTML做标签白名单过滤。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 05:39:01