TwinCAT HMI TE2000 HtmlHost中JS文件模块化导入问题求助
TwinCAT HMI TE2000 HtmlHost 脚本拆分问题
我正在为TwinCAT HMI TE2000的HtmlHost编写JS脚本,当前单个HtmlHost对应一份脚本,但画布绘制功能的代码量已过大,希望将drawGrid这类函数拆分至其他文件,仅在主文件中调用redrawCanvas函数。
尝试了ES模块方案但未成功,相关代码及报错如下:
内容区域代码
<div id="MAIN" data-tchmi-type="TcHmi.Controls.System.TcHmiContent" data-tchmi-top="0" data-tchmi-left="0" data-tchmi-width="100" data-tchmi-height="100" data-tchmi-width-unit="%" data-tchmi-height-unit="%" data-tchmi-creator-viewport-width="1152" data-tchmi-width-mode="Value" data-tchmi-height-mode="Value" data-tchmi-creator-viewport-height="972"> <div id="HtmlHostId" data-tchmi-type="TcHmi.Controls.System.TcHmiHtmlHost" data-tchmi-height="100" data-tchmi-height-unit="%" data-tchmi-left="0" data-tchmi-left-unit="px" data-tchmi-top="0" data-tchmi-top-unit="px" data-tchmi-width="100" data-tchmi-width-unit="%"> <!-- HEADER --> <meta charset="utf-8"> <link rel="stylesheet" href="/static/customStyle.css"> <!-- BODY --> <div id="testDivId"></div> <script src="/static/mainTest.js" type="module"></script> </div> </div>
mainTest.js代码
// Keep these lines for a best effort IntelliSense in the editor. /// <reference path="./../../../Packages/Beckhoff.TwinCAT.HMI.Framework.14.3.500/runtimes/native1.12-tchmi/TcHmi.d.ts" /> if (!window.testScriptInitialized) { (function setTestScript(){ const testDivId document.getElementById('testDivId'); if (!testDivId ){ setTimeout(setTestScript, 100); console.log('HtmlHost not initialized, setting timeout'); return; } console.log('HtmlHost initialized, running setTestScript'); import { testvarWriter } from './testvarFunction.js' testvarWriter(); console.log(testvar1, testvar2); window.testScriptInitialized= true; console.log('setTestScript completed'); })(); }
testvarFunction.js代码
// Keep these lines for a best effort IntelliSense in the editor. /// <reference path="./../../../Packages/Beckhoff.TwinCAT.HMI.Framework.14.3.500/runtimes/native1.12-tchmi/TcHmi.d.ts" /> export function testvarWriter() { const testvar1 = 'hello, i a testvar1'; const testvar2 = 'itsa me, testvar2'; }
控制台报错日志
VM41047 mainTest.js:36 Uncaught SyntaxError: Cannot use import statement outside a module (at VM41047 mainTest.js:36:9) testvarFunction.js:5 Uncaught SyntaxError: Unexpected token 'export' (at testvarFunction.js:5:1) mainTest.js:36 Uncaught SyntaxError: Unexpected token '{' (at mainTest.js:36:16)
目前仅能依赖辅助文件先于主文件加载的方式,但该方案不可靠,请问是否有其他可行的解决方案?
解决方案
方案1:IIFE全局挂载(最稳定)
由于TwinCAT HMI的HtmlHost环境对ES模块支持有限,改用IIFE(立即执行函数表达式)将拆分的函数挂载到全局对象,避免模块语法冲突:
改造testvarFunction.js
/// <reference path="./../../../Packages/Beckhoff.TwinCAT.HMI.Framework.14.3.500/runtimes/native1.12-tchmi/TcHmi.d.ts" /> (function(window) { function testvarWriter() { const testvar1 = 'hello, i a testvar1'; const testvar2 = 'itsa me, testvar2'; // 将变量挂载到全局,供主脚本访问 window.testVars = { testvar1, testvar2 }; } // 统一命名空间,避免全局污染 window.DrawUtils = window.DrawUtils || {}; window.DrawUtils.testvarWriter = testvarWriter; })(window);
改造mainTest.js
/// <reference path="./../../../Packages/Beckhoff.TwinCAT.HMI.Framework.14.3.500/runtimes/native1.12-tchmi/TcHmi.d.ts" /> if (!window.testScriptInitialized) { (function setTestScript(){ const testDivId = document.getElementById('testDivId'); // 修复原代码的语法错误:缺少= // 同时检查HtmlHost和工具脚本是否初始化完成 if (!testDivId || !window.DrawUtils?.testvarWriter){ setTimeout(setTestScript, 100); console.log('HtmlHost或工具脚本未初始化,重试中'); return; } console.log('HtmlHost初始化完成,执行脚本'); // 调用拆分的函数 window.DrawUtils.testvarWriter(); // 访问全局变量 console.log(window.testVars.testvar1, window.testVars.testvar2); window.testScriptInitialized = true; console.log('脚本执行完成'); })(); }
修改HtmlHost脚本加载
<script src="/static/testvarFunction.js"></script> <script src="/static/mainTest.js"></script>
移除type="module",通过主脚本的初始化检查避免加载顺序问题。
方案2:动态导入(异步方式)
如果环境支持动态导入,可在主脚本中用异步加载替代静态import:
改造mainTest.js
/// <reference path="./../../../Packages/Beckhoff.TwinCAT.HMI.Framework.14.3.500/runtimes/native1.12-tchmi/TcHmi.d.ts" /> if (!window.testScriptInitialized) { (async function setTestScript(){ const testDivId = document.getElementById('testDivId'); if (!testDivId ){ setTimeout(setTestScript, 100); console.log('HtmlHost未初始化,重试中'); return; } console.log('HtmlHost初始化完成,加载工具脚本'); try { // 动态导入工具脚本 const { testvarWriter } = await import('./testvarFunction.js'); // 接收函数返回的变量 const { testvar1, testvar2 } = testvarWriter(); console.log(testvar1, testvar2); console.log('脚本执行完成'); } catch (e) { console.error('加载工具脚本失败:', e); setTimeout(setTestScript, 500); // 加载失败重试 } window.testScriptInitialized = true; })(); }
改造testvarFunction.js
/// <reference path="./../../../Packages/Beckhoff.TwinCAT.HMI.Framework.14.3.500/runtimes/native1.12-tchmi/TcHmi.d.ts" /> export function testvarWriter() { const testvar1 = 'hello, i a testvar1'; const testvar2 = 'itsa me, testvar2'; // 返回变量供主脚本使用 return { testvar1, testvar2 }; }
关键注意事项
- 原代码存在语法错误:
const testvarWriter document.getElementById('testDivId');缺少=,需先修复。 - TwinCAT HMI的HtmlHost环境优先推荐IIFE方案,兼容性更稳定。
- 拆分的函数如需访问TwinCAT HMI API,必须在HtmlHost初始化完成后调用(通过主脚本的检查逻辑确保)。
内容的提问来源于stack exchange,提问作者SauceTheSecond




