jQuery动态插入type="module"外部脚本不执行问题咨询
问题
使用jQuery("#some-div").html()设置div内容时遇到以下情况:
- 插入含
alert()的普通内联脚本,如jQuery("#some-div").html("<app-bysquare>Bla bla bla</app-bysquare><script>alert('OK');</script>"),alert可正常触发; - 插入仅含
alert()的外部text/javascript脚本,如jQuery("#some-div").html("<app-bysquare>Bla bla bla</app-bysquare><script type='text/javascript' src='alert.js'></script>"),alert也能正常执行; - 插入带有
import语句、后续包含alert()的外部type="module"脚本,如jQuery("#some-div").html("<app-bysquare>Bla bla bla</app-bysquare><script type='module' src='alert.js'></script>"),alert无法触发。移除import语句后alert可执行,但模块功能会缺失。
实际需求是通过该模块在动态创建的<app-bysquare>元素中生成支付二维码,模块代码示例如下:
import { CurrencyCode, encode, PaymentOptions } from "https://esm.sh/bysquare@2.7.1/"; import { html, LitElement } from "https://esm.sh/lit@3.0.0/"; import { qrcanvas } from "https://esm.sh/qrcanvas@3.1.2/"; alert(); /** * @extends {LitElement} */ class Bysquare extends LitElement { static properties = { _qrstring: { state: true }, _ammount: { state: true }, _variable: { state: true }, _iban: { state: true } }; constructor() { super(); this._qrstring = ""; this._ammount = 10; this._variable = "0026548"; this._iban = "SK9611000000002918599669"; } firstUpdated() { this.#generateQrstring(); } get #canvas() { return this.shadowRoot?.querySelector("canvas"); } render() { return html` <div> <canvas @click=${this.#setCanvas} height="200" width="200" ></canvas> </div> `; } #generateQrstring() { alert(_test); const qrstring = encode({ invoiceId: new Date().toLocaleDateString("sk"), payments: [ { type: PaymentOptions.PaymentOrder, amount: this._ammount, bankAccounts: [{ iban: this._iban }], currencyCode: CurrencyCode.EUR, variableSymbol: this._variable, paymentNote: "Some text here" } ] }); this._qrstring = qrstring; this.#setCanvas(); } #setCanvas() { if (this.#canvas) { const ctx = this.#canvas.getContext("2d"); if (ctx) { ctx.clearRect(0, 0, this.#canvas.width, this.#canvas.height); qrcanvas({ data: this._qrstring, canvas: this.#canvas }); } } } } customElements.define("app-bysquare", Bysquare);
解决方案
问题原因
- 模块脚本加载特性:
type="module"的ES模块是异步加载且作用域隔离的,jQuery的.html()方法插入模块脚本时,无法自动处理模块的依赖加载顺序和作用域绑定,可能导致模块加载失败或未完成时元素已被插入,后续逻辑无法执行。 - 自定义元素注册时机:模块中注册的
<app-bysquare>需要模块加载完成后才能被浏览器识别,若通过.html()提前插入元素,浏览器会将其当作未知元素处理,模块加载完成后也不会自动触发初始化逻辑。
解决办法
方法1:手动创建模块脚本元素插入
避免通过.html()直接插入模块脚本,手动创建脚本元素并监听加载状态:
// 先插入自定义元素 $("#some-div").empty().html("<app-bysquare>Bla bla bla</app-bysquare>"); // 创建模块脚本 const script = document.createElement('script'); script.type = 'module'; script.src = 'alert.js'; // 模块加载完成后确认自定义元素可用 script.onload = () => { console.log('模块加载完成,自定义元素已注册'); }; // 插入脚本到目标容器 $("#some-div").append(script);
方法2:模块内手动初始化已存在元素
若必须先插入元素再加载模块,在模块末尾手动触发元素初始化:
修改模块代码末尾:
customElements.define("app-bysquare", Bysquare); // 初始化已存在的<app-bysquare>元素 document.querySelectorAll('app-bysquare').forEach(el => { if (el.firstUpdated) { el.firstUpdated(); } });
方法3:使用动态import()加载模块
通过异步加载模块确保加载完成后再处理元素:
$("#some-div").html("<app-bysquare>Bla bla bla</app-bysquare>"); // 动态加载模块 import('./alert.js').then(() => { // 模块加载完成,元素可正常渲染 }).catch(err => { console.error('模块加载失败:', err); });
额外注意点
- 模块中的
alert(_test)会报错(_test未定义),需移除或定义该变量,否则模块加载失败会导致后续代码无法执行; - 确保ES模块的
import路径可正常访问,外部依赖资源需能加载成功。
内容的提问来源于stack exchange,提问作者theoneiam
相关产品推荐
相关产品推荐

