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 相关文章推荐
jquery 问答知识整理
Feb 11 Javascript
JavaScript 开发规范要求(图文并茂)
Jun 11 Javascript
jQuery版仿Path菜单效果
Dec 15 Javascript
Jquery写一个鼠标拖动效果实现原理与代码
Dec 24 Javascript
解决Extjs4中form表单提交后无法进入success函数问题
Nov 26 Javascript
JS数组去重与取重的示例代码
Jan 24 Javascript
JavaScript将XML转成JSON的方法
Mar 12 Javascript
node.js插件nodeclipse安装图文教程
Oct 19 Javascript
js图片上传前预览功能(兼容所有浏览器)
Aug 24 Javascript
vue.js中$watch的用法示例
Oct 04 Javascript
Ajax验证用户名或昵称是否已被注册
Apr 05 Javascript
Jquery和CSS实现选择框重置按钮功能
Nov 08 jQuery
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版自动生成文章摘要
2008/07/23 PHP
php学习之 认清变量的作用范围
2010/01/26 PHP
使用array mutisort 实现按某字段对数据排序
2013/06/18 PHP
PHP获取文件夹内文件数的方法
2015/03/12 PHP
php、mysql查询当天,查询本周,查询本月的数据实例(字段是时间戳)
2017/02/04 PHP
TP3.2框架分页相关实现方法分析
2020/06/03 PHP
javascript编程起步(第六课)
2007/01/10 Javascript
使用JQuery和s3captche实现一个水果名字的验证
2009/08/14 Javascript
jquery实现上下左右滑动的方法
2015/02/09 Javascript
初步了解javascript面向对象
2015/11/09 Javascript
基于JavaScript的操作系统你听说过吗?
2016/01/28 Javascript
Javascript之Number对象介绍
2016/06/07 Javascript
jQuery中deferred对象使用方法详解
2016/07/14 Javascript
Javascript es7中比较实用的两个方法示例
2017/07/21 Javascript
[58:42]DOTA2上海特级锦标赛C组败者赛 Newbee VS Archon第一局
2016/02/27 DOTA
[36:16]完美世界DOTA2联赛PWL S3 access vs Rebirth 第一场 12.19
2020/12/24 DOTA
详细介绍Ruby中的正则表达式
2015/04/10 Python
使用Python下的XSLT API进行web开发的简单教程
2015/04/15 Python
python中类变量与成员变量的使用注意点总结
2017/04/29 Python
利用Python批量压缩png方法实例(支持过滤个别文件与文件夹)
2017/07/30 Python
Python入门之三角函数tan()函数实例详解
2017/11/08 Python
Python如何快速上手? 快速掌握一门新语言的方法
2017/11/14 Python
python删除服务器文件代码示例
2018/02/09 Python
Python数据分析库pandas基本操作方法
2018/04/08 Python
pyqt实现.ui文件批量转换为对应.py文件脚本
2019/06/19 Python
PageFactory设计模式基于python实现
2020/04/14 Python
连卡佛中国官网:Lane Crawford中文站
2018/01/27 全球购物
共产党员承诺书
2014/03/25 职场文书
企业指导教师评语
2014/04/28 职场文书
运动会演讲稿200字
2014/08/25 职场文书
村主任群众路线个人对照检查材料
2014/09/26 职场文书
社团个人总结范文
2015/03/05 职场文书
2015年新教师工作总结
2015/04/28 职场文书
浅谈redis的过期时间设置和过期删除机制
2022/03/18 MySQL
python和anaconda的区别
2022/05/06 Python
Redis实现短信验证码登录的示例代码
2022/06/14 Redis