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

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);
解决方案

问题原因

  1. 模块脚本加载特性:type="module"的ES模块是异步加载且作用域隔离的,jQuery的.html()方法插入模块脚本时,无法自动处理模块的依赖加载顺序和作用域绑定,可能导致模块加载失败或未完成时元素已被插入,后续逻辑无法执行。
  2. 自定义元素注册时机:模块中注册的<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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 14:20:55