我正在尝试使用MathJax在我的Angular 2
应用中显示公式。我的应用程序中只有一小部分确实需要此功能,因此我不希望所有用户都必须下载所需的3-400kb。
我最初的想法是在我的组件中import "mathjax"
,因此只有在创建组件时才会加载库。但是,我了解到from my earlier question MathJax并不能很好地与其他人合作,因为它使用自己的自定义模块加载器。
我当前的设置会从script
加载index.html
,但这意味着当只有一小部分用户需要此组件时,所有人将下载
<script src="https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=AM_SVG"></script>
在Angular 2
中是否有一种干净的方法让我的组件在ngOnInit()
挂钩中下载脚本并在DOM中执行回调?诸如(伪代码)之类的东西:
ngOnInit(){
//download script, add to DOM
fetch('https://...MathJax.js').then(addToDom).then(this.onMathJaxLoaded);
}
onMathJaxLoaded(){
// Run math renderer
MathJax.Hub.Queue("Typeset",...);
}
答案 0 :(得分:6)
我没试过,但我认为这可能是可能的:
ngOnInit(){
//download script, add to DOM
var script = document.createElement('script');
document.body.appendChild(script)
script.onload = this.onMathJaxLoaded.bind(this);
script.src = 'https://...MathJax.js';
}
onMathJaxLoaded(){
// Run math renderer
MathJax.Hub.Queue("Typeset",...);
}
这是一个小提琴,其中包含一个如何在纯JavaScript中工作的示例; https://jsfiddle.net/5qu5h7bc/
答案 1 :(得分:2)
在@ TryingToImprove的解决方案的基础上,我决定使用ScriptLoaderService
函数向我的应用添加load()
,该函数提取远程脚本并通知调用者(使用RxJS Observable })当它完成。
以下是如何使用它:
this.scriptLoaderService.load('https://...js').subscribe(
()=>console.log('script has loaded');
);
这是服务:
/**
* A directory of scripts that have been or are being loaded
*/
private scripts = new Map<string,Observable<boolean>|boolean>();
/**
* Downloads script; returns Observable that emits TRUE once "load" event fires
*/
public load(src:string):Observable<boolean>{
if(this.scripts.has(src)){
// If script has already been fully loaded.
if(this.scripts.get(src)===true) return Observable.of(true);
// Else if download is already underway but load event hasn't fired yet
else return this.scripts.get(src);
}
//Add a script tag to the DOM
let script = document.createElement('script');
document.body.appendChild(script);
// upon subscription, listen for the load event. Once it arrives, emit TRUE
let obs:Observable<boolean> = Observable.fromEvent(script,'load')
// Map should hold TRUE once script is loaded
.do(()=> this.scripts.set(src,true))
.take(1).map(e=>true);
// set the src attribute (will cause browser to download)
script.src = src;
//add observable to the scripts Map
this.scripts.set(src,obs);
return obs;
}
在Firefox 51