php动态加载js,动态加载 js

前端项目中使用到了一个报表库 Plotly.js, 这个库有 600多k。由于报表只有部分模块用到,所以想使用动态加载方式。

首先想到使用 webpack 的懒加载,但是打包时间太长。加这个库之前 30秒,加之后 6 分钟。使用 noParse 也没有效果。

所以决定用到时,手动加载。

js 常用的动态加载有两种。ajax 加载后使用 eval 执行。或者使用 script 标签加载。

这里介绍动态创建标签的方法。不说了,直接上代码:

// Attach handlers for all browsers

var loadScript = function (path, callback) {

const me = this;

const script = document.createElement('script');

script.type = 'text/javascript';

let done = false;

const head = document.head;

const error = () => {

if (!done) {

done = true;

script.onload = script.onreadystatechange = script.onerror = null;

head.removeChild(script);

callback(false);

}

}

const success = () => {

if (!done) {

done = true;

script.onload = script.onreadystatechange = script.onerror = null;

head.removeChild(script);

callback(true);

}

}

script.onreadystatechange = function () {

if (this.readyState == "loaded" || this.readyState == "complete") {

success();

}

};

script.onload = success;

script.onerror = error;

script.src = path;

head.appendChild(script);

}

上面是动态加载js的方法。但是可能多个模块会用到这个js库。当同时打开这些模块时,有可能会导致多次加载。所以可以把加载后的模块根据路径缓存起来。

下面代码是使用 TypeScript 写的, 根据路径记录 js 文件加载信息,避免重复:

export default class LoadJs {

public static loadSync(path: string): Promise {

const me = this;

return new Promise((resolve, reject) => {

me.load(path, (bSuc) => {

if (bSuc) {

resolve();

} else {

reject();

}

});

});

}

public static load(path: string, callback: (bSuc: boolean) => void): void {

let lib = this.pathLoaded[path];

// 没有记录,添加记录

if (!lib) {

lib = {

isLoaded: false,

callback: [callback],

};

this.pathLoaded[path] = lib;

}

// 已加载直接返回

if (lib.isLoaded) {

callback(true);

} else {

// 添加回调

lib.callback.push(callback);

// 加载

const me = this;

this.loadScript(path, suc => {

if (suc) {

me.onLoad(lib, true);

} else {

me.onLoad(lib, false);

}

})

}

}

private static loadScript(path, callback) {

const me = this;

const script = document.createElement('script') as any;

script.type = 'text/javascript';

let done = false;

const head = document.head;

const error = () => {

if (!done) {

done = true;

script.onload = script.onreadystatechange = script.onerror = null;

head.removeChild(script);

callback(false);

}

}

const success = () => {

if (!done) {

done = true;

script.onload = script.onreadystatechange = script.onerror = null;

head.removeChild(script);

callback(true);

}

}

script.onreadystatechange = function () {

if (this.readyState == "loaded" || this.readyState == "complete") {

success();

}

};

script.onload = success;

script.onerror = error;

script.src = path;

head.appendChild(script);

}

private static pathLoaded: { [key: string]: PathLoading } = {};

private static onLoad(p: PathLoading, isSuc: boolean): void {

p.isLoaded = true;

for (const fun of p.callback) {

fun(isSuc);

}

p.callback = [];

}

}

interface PathLoading {

isLoaded: boolean;

callback: Array void>;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值