vue 或 react 动态加载混合 JavaScript 片段

发布于 2023-02-12
如网站有一个自定义 JS 功能,然后用户输入了这样一个内容:

如网站有一个自定义 JS 功能,然后用户输入了这样一个内容:

<script src="https://xxx.com/Base64/1.1.0/base64.js" type="application/javascript"></script>
console.log(1)
<script src="https://xxx.com/jquery/3.6.0/jquery.js" type="application/javascript"></script>
console.log(2)

<script>
console.log(3);
console.log(4);
</script>

<script>
console.log(5);
</script>

其中包含两段引入外部 js 的语句,还包含两行未由 <script> 包裹的 js 代码,还有两段包含在 <script> 中的代码。想让这些代码都正常执行。

可以使用下面的方式:

const loadScriptDom = (scriptDom) => {
  if (scriptDom) {
    document.getElementsByTagName('head')[0].appendChild(scriptDom);
    console.log(`加载自定义 js, src:${scriptDom.src}, text:${scriptDom.text}`);
  }
}

const loadScriptText = (scriptText) => {
  if (scriptText && scriptText.trim()) {
    let scriptDom = document.createElement('script');
    scriptDom.type = 'text/javascript';
    scriptDom.text = scriptText;
    loadScriptDom(scriptDom);
  }
}

// 自定义 js 拍段
let customJsStr = "...";
if (customJsStr) {
    // 创建一个新的 div 元素
    const tempDivDom = document.createElement('div');
    // 将字符串作为 HTML 插入到新的 div 中
    tempDivDom.innerHTML = customJsStr;
    // 遍历新 div 中的所有 script 元素
    Array.from(tempDivDom.getElementsByTagName('script')).forEach(script => {
      // 如果该 script 元素有 src 属性,则动态引入外部 JavaScript
      if (script.src) {
          const newScript = document.createElement('script');
          for (let i = 0; i < script.attributes.length; i++) {
            const attr = script.attributes[i];
            newScript.setAttribute(attr.name, attr.value);
          }
          loadScriptDom(newScript);
      } else {
          // 否则,执行内联的 JavaScript 代码
          loadScriptText(script.innerHTML);
      }

      // 删除已加载的片段
      tempDivDom.removeChild(script);
    });
    // 将剩余未经 script 包裹的片段加载
    loadScriptText(tempDivDom.innerHTML);
}