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 相关文章推荐
javascript读取xml
Nov 04 Javascript
jquery中实现标签切换效果的代码
Mar 01 Javascript
Jquery判断$("#id")获取的对象是否存在的方法
Sep 25 Javascript
jQuery学习笔记之jQuery构建函数的7种方法
Jun 03 Javascript
Easyui 之 Treegrid 笔记
Apr 29 Javascript
第一次接触Bootstrap框架
Oct 24 Javascript
Vue.2.0.5实现Class 与 Style 绑定的实例
Jun 20 Javascript
Angularjs实现控制器之间通信方式实例总结
Mar 27 Javascript
微信小程序之判断页面滚动方向的示例代码
Aug 30 Javascript
详解js访问对象的属性和方法
Oct 25 Javascript
vue实现滑动到底部加载更多效果
Oct 27 Javascript
JS数组的常用方法整理
Mar 31 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_unique() - 去除数组中重复的元素值
2011/10/29 PHP
php字符串截取函数用法分析
2014/11/25 PHP
php实现redis数据库指定库号迁移的方法
2015/01/14 PHP
windows下安装php的memcache模块的方法
2015/04/07 PHP
TP5(thinkPHP5框架)基于bootstrap实现的单图上传插件用法示例
2019/05/29 PHP
JQuery autocomplete 使用手册
2010/04/01 Javascript
javascript不可用的问题探究
2013/10/01 Javascript
JS小功能(checkbox实现全选和全取消)实例代码
2013/11/28 Javascript
jQuery中after()方法用法实例
2014/12/25 Javascript
javascript解析xml实现省市县三级联动的方法
2015/07/25 Javascript
vue二级菜单导航点击选中事件的方法
2018/09/12 Javascript
JSON基本语法及与JavaScript的异同实例分析
2019/01/04 Javascript
jQuery实现的导航条点击后高亮显示功能示例
2019/03/04 jQuery
jQuery实现动态生成年月日级联下拉列表示例
2019/05/11 jQuery
在vue中利用全局路由钩子给url统一添加公共参数的例子
2019/11/01 Javascript
js实现前端界面导航栏下拉列表
2020/08/27 Javascript
[03:10]2014DOTA2 TI马来劲旅Titan首战告捷目标只是8强
2014/07/10 DOTA
Python实现扩展内置类型的方法分析
2017/10/16 Python
python开启摄像头以及深度学习实现目标检测方法
2018/08/03 Python
python向字符串中添加元素的实例方法
2019/06/28 Python
ubuntu上安装python的实例方法
2019/09/30 Python
python对接ihuyi实现短信验证码发送
2020/05/10 Python
利用python 读写csv文件
2020/09/10 Python
python生成xml时规定dtd实例方法
2020/09/21 Python
加拿大知名的国际儿童品牌:Hatley
2016/11/09 全球购物
Kneipp克奈圃美国官网:德国百年精油配方的传承
2018/02/07 全球购物
婴儿地球:Baby Earth
2018/12/25 全球购物
大唐面试试题(CPU,UNIX等等)
2012/01/11 面试题
高级方案规划工程师岗位职责
2013/11/29 职场文书
团日活动总结
2014/04/28 职场文书
厨师长岗位职责范本
2014/08/25 职场文书
员工试用期自我评价
2014/09/18 职场文书
2014年群众路线党员自我评议
2014/09/24 职场文书
辞职信怎么写
2015/02/27 职场文书
工程款催款函
2015/06/24 职场文书
nginx结合openssl实现https的方法
2021/07/25 Servers