Angular中使用MathJax遇到的一些问题


Posted in Javascript onDecember 15, 2017

前言

话说我本来是倾向于 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();
 }
 }
 }
}

事实证明,它能圆满完成任务,它也就是现在运行在 这个网站 上的代码。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

Javascript 相关文章推荐
图片动画横条广告带上下滚动可自定义图片、链接等等
Oct 20 Javascript
javascript中字符串的定义示例代码
Dec 19 Javascript
使用javascript将时间转换成今天,昨天,前天等格式
Jun 25 Javascript
深入理解jQuery 事件处理
Jun 14 Javascript
JavaScript随机打乱数组顺序之随机洗牌算法
Aug 02 Javascript
AngularJS Phonecat实例讲解
Nov 21 Javascript
vue拦截器Vue.http.interceptors.push使用详解
Apr 22 Javascript
vue实现移动端悬浮窗效果
Dec 01 Javascript
django js 实现表格动态标序号的实例代码
Jul 12 Javascript
微信小程序实现滚动加载更多的代码
Dec 06 Javascript
Vue中this.$nextTick的作用及用法
Feb 04 Javascript
Vue中使用better-scroll实现轮播图组件
Mar 07 Javascript
vue实现验证码输入框组件
Dec 14 #Javascript
基于滚动条位置判断的简单实例
Dec 14 #Javascript
微信小程序实现动态设置placeholder提示文字及按钮选中/取消状态的方法
Dec 14 #Javascript
ES6/JavaScript使用技巧分享
Dec 14 #Javascript
Django与Vue语法的冲突问题完美解决方法
Dec 14 #Javascript
浅析JS抽象工厂模式
Dec 14 #Javascript
JavaScript重复元素处理方法分析【统计个数、计算、去重复等】
Dec 14 #Javascript
You might like
php使用array_rand()函数从数组中随机选择一个或多个元素
2014/04/28 PHP
Laravel 批量更新多条数据的示例
2017/11/27 PHP
PHP For循环字母A-Z当超过26个字母时输出AA,AB,AC
2020/02/16 PHP
jQuery ajax在GBK编码下表单提交终极解决方案(非二次编码方法)
2010/10/20 Javascript
ajax java 实现自动完成功能
2012/12/19 Javascript
Ext GridPanel加载完数据后进行操作示例代码
2014/06/17 Javascript
详解JavaScript数组的操作大全
2015/10/19 Javascript
jQuery1.9+中删除了live以后的替代方法
2016/06/17 Javascript
jQuery层级选择器实例代码
2017/02/06 Javascript
Three.js的使用及绘制基础3D图形详解
2017/04/27 Javascript
获取layer.open弹出层的返回值方法
2018/08/20 Javascript
详解react内联样式使用webpack将px转rem
2018/09/13 Javascript
ajax跨域访问遇到的问题及解决方案
2019/05/23 Javascript
js getBoundingClientRect使用方法详解
2019/07/17 Javascript
基于vue 实现表单中password输入的显示与隐藏功能
2019/07/19 Javascript
js中script的上下放置区别,Dom的增删改创建操作实例分析
2019/12/16 Javascript
全面解析js中的原型,原型对象,原型链
2021/01/25 Javascript
星球大战与Python之间的那些事
2016/01/07 Python
python不换行之end=与逗号的意思及用途
2017/11/21 Python
Python IDLE清空窗口的实例
2018/06/25 Python
Python 脚本拉取 Docker 镜像问题
2019/11/10 Python
解决pycharm每次打开项目都需要配置解释器和安装库问题
2020/02/26 Python
python爬虫学习笔记之pyquery模块基本用法详解
2020/04/09 Python
如何以Winsows Service方式运行JupyterLab
2020/08/30 Python
教你如何一步一步用Canvas写一个贪吃蛇
2018/10/22 HTML / CSS
澳大利亚排名第一的露营和户外设备在线零售商:Outbax
2020/05/06 全球购物
水电工岗位职责
2014/02/12 职场文书
军训自我鉴定范文
2014/02/13 职场文书
交通事故赔偿协议书
2014/04/15 职场文书
学生安全责任书模板
2014/07/25 职场文书
领导干部群众路线个人对照检查材料思想汇报
2014/09/30 职场文书
上帝也疯狂观后感
2015/06/09 职场文书
同事离别感言
2015/08/04 职场文书
防溺水主题班会教案
2015/08/12 职场文书
2016继续教育培训学习心得体会
2016/01/19 职场文书
pytorch中[..., 0]的用法说明
2021/05/20 Python