Vue.js动态加载JS后无法调用updateNode等函数的问题咨询
问题
在Vue.js项目中加载本地脚本与外部脚本时遇到两个问题:
- 最初在组件顶部导入本地脚本,同时在
mounted钩子中加载外部脚本,因本地脚本依赖外部脚本但先加载完成,导致脚本内部分值/函数未定义。 - 将本地脚本移至外部脚本加载完成后的
mounted钩子中导入,脚本加载成功,但调用本地脚本的updateNode()和updateEdge()函数时提示未定义,尝试this.updateNode()、window.updateNode()、m.updateNode()均无效,复制函数到组件methods也失败。
相关代码:
Vue组件
<template> <div class="text-center aParent"> <div id="mynetwork"></div> <div class="add_box"> <h2>add node</h2> node id (int)<input type="text" id="newID"><br> label text (text)<input type="text" id="newLabel"><br> <input type="button" value="Update" @click="updateNode()"> <h2>add edge</h2> from id (int)<input type="text" id="newEdgeFromID"><br> to id (int)<input type="text" id="newEdgeToID"><br> edge text (text)<input type="text" id="newEdgeLabel"><br> <input type="button" value="Update" @click="updateEdge()"> </div> </div> </template> <script> export default { mounted() { let externalScript = document.createElement('script') externalScript.setAttribute('src', 'https://unpkg.com/vis-network/standalone/umd/vis-network.min.js') document.head.appendChild(externalScript) externalScript.onload = () => { import('../../../backend/src/resources/js/questionTree').then(m => { }); } } } </script>
questionTree.js
function updateNode(){ var inputID = parseInt(document.getElementById("newID").value) var inputLabel = document.getElementById("newLabel").value var pushData = addNodeAttribute({id: inputID, label: inputLabel}) nodes.update(addNodeAttribute(pushData)) } function updateEdge(){ var inputFromID = parseInt(document.getElementById("newEdgeFromID").value) var inputToID= parseInt(document.getElementById("newEdgeToID").value) var inputLabel = document.getElementById("newEdgeLabel").value var pushData = {from: inputFromID, to: inputToID, label: inputLabel} edges.update(addEdgeAttribute(pushData)) } function addNodeAttribute(node){ node.shape = "box" node.physics = false node.title = "node ID:\n" + node.id if (node.qa == "q"){ node.color = {border:"black", background:"lightgray", highlight:{ border: "red", background: "orange"}} }else{ node.color = {border:"black", background:"lightblue", highlight:{ border: "red", background: "orange"}} } return node }
解决方案
1. 修正本地脚本的模块导出
原questionTree.js中的函数默认处于模块作用域,外部无法直接访问,需要显式导出函数及依赖的变量(如nodes、edges):
// 初始化vis-network的数据集(确保vis已加载) export let nodes = new window.vis.DataSet(); export let edges = new window.vis.DataSet(); export function updateNode(){ var inputID = parseInt(document.getElementById("newID").value) var inputLabel = document.getElementById("newLabel").value var pushData = addNodeAttribute({id: inputID, label: inputLabel}) nodes.update(pushData); // 移除重复的addNodeAttribute调用 } export function updateEdge(){ var inputFromID = parseInt(document.getElementById("newEdgeFromID").value) var inputToID= parseInt(document.getElementById("newEdgeToID").value) var inputLabel = document.getElementById("newEdgeLabel").value var pushData = {from: inputFromID, to: inputToID, label: inputLabel} edges.update(addEdgeAttribute(pushData)) } export function addNodeAttribute(node){ node.shape = "box" node.physics = false node.title = "node ID:\n" + node.id if (node.qa == "q"){ node.color = {border:"black", background:"lightgray", highlight:{ border: "red", background: "orange"}} }else{ node.color = {border:"black", background:"lightblue", highlight:{ border: "red", background: "orange"}} } return node } // 新增初始化网络的函数,确保组件能正确创建vis实例 export function initNetwork() { const container = document.getElementById('mynetwork'); const data = { nodes, edges }; const options = {}; return new window.vis.Network(container, data, options); }
2. 在Vue组件中保存模块引用并绑定调用
在组件中保存导入的模块引用,通过组件方法间接调用脚本中的函数,确保作用域正确:
<template> <div class="text-center aParent"> <div id="mynetwork"></div> <div class="add_box"> <h2>add node</h2> node id (int)<input type="text" id="newID"><br> label text (text)<input type="text" id="newLabel"><br> <input type="button" value="Update" @click="handleUpdateNode"> <h2>add edge</h2> from id (int)<input type="text" id="newEdgeFromID"><br> to id (int)<input type="text" id="newEdgeToID"><br> edge text (text)<input type="text" id="newEdgeLabel"><br> <input type="button" value="Update" @click="handleUpdateEdge"> </div> </div> </template> <script> export default { data() { return { questionTreeModule: null // 保存导入的本地脚本模块 } }, async mounted() { await new Promise((resolve) => { // 加载外部脚本 const externalScript = document.createElement('script') externalScript.src = 'https://unpkg.com/vis-network/standalone/umd/vis-network.min.js' externalScript.onload = resolve document.head.appendChild(externalScript) }); // 导入本地脚本并保存模块引用 this.questionTreeModule = await import('../../../backend/src/resources/js/questionTree') // 初始化vis网络 this.questionTreeModule.initNetwork() }, methods: { handleUpdateNode() { // 确保模块已加载再调用函数 this.questionTreeModule?.updateNode() }, handleUpdateEdge() { this.questionTreeModule?.updateEdge() } } } </script>
可选方案:全局挂载函数(不推荐)
如果不想修改模块导出,可以在questionTree.js中将函数挂载到window对象:
window.updateNode = function(){ // 原函数内容 } window.updateEdge = function(){ // 原函数内容 }
然后在Vue组件的方法中直接调用:
methods: { handleUpdateNode() { window.updateNode() }, handleUpdateEdge() { window.updateEdge() } }
此方法会污染全局作用域,仅适合小型项目临时使用。
内容的提问来源于stack exchange,提问作者maz32
相关产品推荐
相关产品推荐

