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

Vue如何引入含DOMContentLoaded的JS文件并传递组件变量?

在Vue中加载外部JS并传递变量的解决方案

我需要在Vue组件中加载一个外部JS文件,并且向该文件传递变量。这个JS在纯HTML的head标签里引入就能正常运行,但在Vue里尝试动态创建script标签的方式行不通。

目标外部JS代码

document.addEventListener('DOMContentLoaded', () => {
  const userGrid = document.querySelector('.grid-user') //done
  const computerGrid = document.querySelector('.grid-computer') //done
  const displayGrid = document.querySelector('.grid-display')
  const ships = document.querySelectorAll('.ship')

  createBoard(userGrid, userSquares)
  createBoard(computerGrid, computerSquares)

  function startSinglePlayer() {
    generate(shipArray[0])
    generate(shipArray[1])
    generate(shipArray[2])
    generate(shipArray[3])
    generate(shipArray[4])

    startButton.addEventListener('click', () => {
      setupButtons.style.display = 'none'
      playGameSingle()
    })
  }

  //Create Board
  function createBoard(grid, squares) {
    for (let i = 0; i < width*width; i++) {
      const square = document.createElement('div')
      square.dataset.id = i
      grid.appendChild(square)
      squares.push(square)
    }
  }

  // 其他未展示的代码...
})

我尝试过的无效写法

mounted() {
    const plugin = document.createElement("script");
    plugin.setAttribute(
      "src",
      "//api.myplugincom/widget/mykey.js"
    );
    plugin.async = true;
    document.head.appendChild(plugin);
  }

问题原因

原JS依赖DOMContentLoaded事件触发执行,但Vue组件的mounted钩子执行时,页面的DOMContentLoaded事件大概率已经触发完毕,导致外部JS里的代码不会执行。另外,原JS中使用的userSquares、width、shipArray等变量都是全局依赖,在Vue中需要专门处理变量传递。

解决方案

方案一:修改外部JS为模块化可调用形式(推荐)

把原JS改成可接收参数的函数,脱离对DOMContentLoaded的依赖:

// 改写后的外部JS
export function initGame(options) {
  // 解构传入的参数
  const { 
    userGrid, 
    computerGrid, 
    displayGrid, 
    ships, 
    userSquares, 
    computerSquares, 
    width, 
    shipArray, 
    startButton, 
    setupButtons 
  } = options;

  createBoard(userGrid, userSquares);
  createBoard(computerGrid, computerSquares);

  function startSinglePlayer() {
    generate(shipArray[0]);
    generate(shipArray[1]);
    generate(shipArray[2]);
    generate(shipArray[3]);
    generate(shipArray[4]);

    startButton.addEventListener('click', () => {
      setupButtons.style.display = 'none';
      playGameSingle();
    });
  }

  function createBoard(grid, squares) {
    for (let i = 0; i < width*width; i++) {
      const square = document.createElement('div');
      square.dataset.id = i;
      grid.appendChild(square);
      squares.push(square);
    }
  }

  // 保留原有的其他函数(比如generate、playGameSingle)...
  
  // 启动游戏逻辑
  startSinglePlayer();
}

// 兼容非模块化环境,挂载到window
if (typeof window !== 'undefined') {
  window.initGame = initGame;
}

然后在Vue组件中调用:

<template>
  <div>
    <div class="grid-user" ref="userGrid"></div>
    <div class="grid-computer" ref="computerGrid"></div>
    <div class="grid-display" ref="displayGrid"></div>
    <div class="ship" ref="ships"></div>
    <button ref="startButton">开始游戏</button>
    <div ref="setupButtons">设置区域</div>
  </div>
</template>

<script>
// 如果是本地JS文件,直接导入
import { initGame } from './path/to/your/game.js';

export default {
  data() {
    return {
      width: 10, // 游戏棋盘宽度,根据实际需求设置
      userSquares: [],
      computerSquares: [],
      shipArray: [/* 你的船型数据数组 */]
    };
  },
  mounted() {
    // 调用外部JS的初始化函数,传入所需参数
    initGame({
      userGrid: this.$refs.userGrid,
      computerGrid: this.$refs.computerGrid,
      displayGrid: this.$refs.displayGrid,
      ships: this.$refs.ships,
      userSquares: this.userSquares,
      computerSquares: this.computerSquares,
      width: this.width,
      shipArray: this.shipArray,
      startButton: this.$refs.startButton,
      setupButtons: this.$refs.setupButtons
    });

    // 如果是CDN加载的外部JS,改用以下方式:
    // const script = document.createElement('script');
    // script.src = '//api.myplugincom/widget/mykey.js';
    // script.onload = () => {
    //   window.initGame({ /* 传入上述参数 */ });
    // };
    // document.head.appendChild(script);
  }
};
</script>

方案二:不修改外部JS,适配Vue生命周期(仅适用于无法修改外部JS的场景)

通过挂载全局变量、确保脚本加载时机来适配:

<script>
export default {
  data() {
    return {
      width: 10,
      userSquares: [],
      computerSquares: [],
      shipArray: [/* 你的数据 */]
    };
  },
  mounted() {
    // 先把依赖的变量挂载到window全局,供外部JS读取
    window.width = this.width;
    window.userSquares = this.userSquares;
    window.computerSquares = this.computerSquares;
    window.shipArray = this.shipArray;

    // 创建script标签加载外部JS
    const script = document.createElement('script');
    script.src = '//api.myplugincom/widget/mykey.js';
    // 脚本加载完成后,若DOMContentLoaded已触发,手动执行核心逻辑
    script.onload = () => {
      // 这里需要知道外部JS里的核心函数名,比如如果原逻辑是在一个匿名函数里,可能需要手动模拟触发
      // 例如,如果原JS的核心逻辑是绑定在DOMContentLoaded上的,可尝试重新执行该逻辑
      // 注意:这种方式可靠性较低,容易出问题
    };
    document.head.appendChild(script);
  }
};
</script>

注意事项

  • 优先选择方案一,模块化的方式更符合Vue的开发规范,避免全局变量污染,参数传递更清晰
  • 方案二依赖全局变量,容易引发命名冲突,仅作为无法修改外部JS时的妥协方案
  • 无论哪种方案,都要确保Vue组件中的DOM元素已经渲染完成(mounted钩子满足这个条件),避免外部JS找不到DOM节点

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 12:20:38