Angular中使用MathJax遇到的一些问题
前言
话说我本来是倾向于 katex 的,因为我感觉他很快,而且 mathjax 似乎很难配。但是大家表示对缺少功能的 katex 并无好感,给我提供了一些钻研 mathjax 的动力。
mathjax简介
mathjax是一款运行在浏览器中的开源数学符号渲染引擎,使用mathjax可以方便的在浏览器中显示数学公式,不需要使用图片。目前,mathjax可以解析latex、mathml和asciimathml的标记语言。mathjax项目于2009年开始,发起人有american mathematical society, design science等,还有众多的支持者,个人感觉mathjax会成为今后数学符号渲染引擎中的主流,也许现在已经是了。
个人其实也不算钻研,因为实际上 mathjax 很简单,调用 mathjax.hub.queue(['typeset', mathjax.hub, this.element.nativeelement]);
就可以渲染一个元素(这个 this.element.nativeelement 是从 angular 中调用它 dom 的语法),这个 .queue 实际上是 mathjax 自己实现的回调格式,语法非常清奇,参数个数不定,每个都是数组,代表一个回调,顺序执行。比如这个 ['typeset', mathjax.hub, this.element.nativeelement] ,第一个元素是方法名,第二个元素是 this ,之后的元素都是参数……
我们可以看到这个就相当于执行 mathjax.hub.typeset(this.element.nativeelement)
,那为啥不执行这个?因为这方法是同步的,会导致页面十分卡。于是 mathjax 就自己封装了一个异步队列(它的 api 可能几百年没改了)
我们说回 angular。因为要用 markdown,我的思路是用 marked 封装一个 directive。那么我们就应该在 marked 渲染完成之后用 mathjax 去 typeset 这个组件。但真的这样做了,却产生了奇妙的效果——切换页面之后,要等将近一分钟才开始渲染。我在它的队列里放了几个 log,发现每个元素都被 queue 了 4 次,几十个元素,难怪要一分钟才开始渲染下一页的内容,即使大部分 markdown 里面根本没有数学。
这时候我开始灰心了,这个问题就没有解决办法了吗?绝望之时,我想到能不能直接 typeset document,结果是可以的,而且十分快。所以渲染并不慢,可能是渲染的初始化过程比较慢。那么这时候方案就出来了,我们可以尽量减少渲染次数,同时只渲染 document。只要这个渲染还在进行,那么有再多的元素 queue 上来,我们也只当作 queue 了一次。
于是我就写了这么个 service:
@injectable() export class mathjaxservice { public isqueued = false; public isrunning = false; window: any; constructor(@inject(platform_id) private platformid: object) { if (isplatformbrowser(this.platformid)) { this.window = window as any; } } finishrunning() { this.isrunning = false; if (this.isqueued) { this.queuechange(); } } queuechange() { if (this.isrunning) { this.isqueued = true; } else { this.isqueued = false; this.isrunning = true; if (isplatformbrowser(this.platformid)) { if (this.window.mathjax) { this.window.mathjax.hub.config({ messagestyle: 'none', tex2jax: { // preview: 'none', inlinemath: [['$', '$']], processescapes: true } }); this.window.mathjax.hub.queue(['log', console, 'start'], ['typeset', this.window.mathjax.hub, document], ['log', console, 'end'], ['finishrunning', this]); } } else { this.finishrunning(); } } } }
事实证明,它能圆满完成任务,它也就是现在运行在 上的代码。
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对的支持。