在Vue 3项目中执行API返回的script标签内JavaScript代码是否可行?
Vue 3 执行API返回内容中script标签的实现方案
该需求可以实现,Vue仅默认阻止动态插入的script标签自动执行,并非完全无法完成该操作,以下是两种可行的实现方式:
方案1:手动解析执行script标签
拿到API返回的完整HTML字符串后,先将静态HTML、CSS插入到页面容器中,再手动提取所有script标签,通过创建新的script节点替换原有节点的方式触发脚本执行,示例代码如下:
<script setup> import { ref, onMounted } from 'vue' // 承载动态内容的DOM容器 const dynamicContent = ref() const loadApiContent = async () => { const res = await fetch('你的业务API地址') const rawContent = await res.text() // 先插入静态HTML和CSS dynamicContent.value.innerHTML = rawContent // 提取所有script标签手动执行 const originScripts = dynamicContent.value.querySelectorAll('script') originScripts.forEach(oldScript => { const newScript = document.createElement('script') // 复制原有script的所有属性 Array.from(oldScript.attributes).forEach(attr => { newScript.setAttribute(attr.name, attr.value) }) // 复制内联脚本内容 newScript.textContent = oldScript.textContent // 替换旧节点,新插入的script会自动执行 oldScript.parentNode.replaceChild(newScript, oldScript) }) } onMounted(() => { loadApiContent() }) </script> <template> <div ref="dynamicContent"></div> </template>
方案2:iframe沙箱隔离执行(更安全)
如果不希望动态脚本污染主应用的全局上下文、降低安全风险,可以用iframe作为独立容器加载完整的返回内容,iframe内的脚本会自动执行,和主应用完全隔离,示例代码如下:
<script setup> import { onMounted } from 'vue' const loadApiContent = async () => { const res = await fetch('你的业务API地址') const rawContent = await res.text() const iframe = document.querySelector('#contentIframe') const iframeDoc = iframe.contentDocument || iframe.contentWindow.document iframeDoc.open() iframeDoc.write(rawContent) iframeDoc.close() } onMounted(() => { loadApiContent() }) </script> <template> <iframe id="contentIframe" sandbox="allow-scripts allow-same-origin" style="width: 100%; min-height: 600px; border: none;" ></iframe> </template>
安全注意事项
执行外部来源的未知JavaScript属于极高风险操作,仅在你完全信任API返回内容的前提下使用。生产环境部署前请务必做好内容安全校验、恶意代码筛查、内容签名校验等防护措施,避免出现XSS攻击、用户敏感数据泄露等严重安全问题
内容的提问来源于stack exchange,提问作者Rishabh Gupta
相关产品推荐
相关产品推荐

