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 支持链式调用的异步调用框架Async.Operation
Aug 04 Javascript
js阻止冒泡及jquery阻止事件冒泡示例介绍
Nov 19 Javascript
JavaScript字符串对象charAt方法入门实例(用于取得指定位置的字符)
Oct 17 Javascript
JS使用正则表达式除去字符串中重复字符的方法
Nov 05 Javascript
jquery 点击元素后,滚动条滚动至该元素位置的方法
Aug 05 Javascript
JavaScript自执行函数和jQuery扩展方法详解
Oct 27 jQuery
mint-ui的search组件在键盘显示搜索按钮的实现方法
Oct 27 Javascript
vue实现微信分享朋友圈,发送朋友的示例讲解
Feb 10 Javascript
使用JS获取页面上的所有标签
Oct 18 Javascript
通过vue手动封装on、emit、off的代码详解
May 29 Javascript
Vue中通过Vue.extend动态创建实例的方法
Aug 13 Javascript
VUE路由动态加载实例代码讲解
Aug 26 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
星际争霸 Starcraft 编年史
2020/03/14 星际争霸
PHP 导出数据到淘宝助手CSV的方法分享
2010/02/27 PHP
mysql From_unixtime及UNIX_TIMESTAMP及DATE_FORMAT日期函数
2010/03/21 PHP
php文件读取方法实例分析
2015/06/20 PHP
thinkphp命名空间用法实例详解
2015/12/30 PHP
Yii框架结合sphinx,Ajax实现搜索分页功能示例
2016/10/18 PHP
PHP文件管理之实现网盘及压缩包的功能操作
2017/09/20 PHP
如何在centos8自定义目录安装php7.3
2019/11/28 PHP
javascript 动态数据下的锚点错位问题解决方法
2008/12/24 Javascript
javascript 放大镜效果js组件 qsoft.PopBigImage.v0.35 加入了chrome支持
2009/04/07 Javascript
Javascript在IE或Firefox下获取鼠标位置的代码
2009/12/18 Javascript
深入分析js中的constructor和prototype
2012/04/07 Javascript
jquery $.fn $.fx是什么意思有什么用
2013/11/04 Javascript
轻松玩转BootstrapTable(后端使用SpringMVC+Hibernate)
2017/09/06 Javascript
cocos creator Touch事件应用(触控选择多个子节点的实例)
2017/09/10 Javascript
对vue.js中this.$emit的深入理解
2018/02/23 Javascript
layui默认选中table的CheckBox复选框方法
2019/09/19 Javascript
JSON stringify方法原理及实例解析
2020/10/23 Javascript
用Python中的wxPython实现最基本的浏览器功能
2015/04/14 Python
python实现rsa加密实例详解
2017/07/19 Python
基于Django的ModelForm组件(详解)
2017/12/07 Python
python队列通信:rabbitMQ的使用(实例讲解)
2017/12/22 Python
Django实现全文检索的方法(支持中文)
2018/05/14 Python
详解用python生成随机数的几种方法
2019/08/04 Python
Python3和PyCharm安装与环境配置【图文教程】
2020/02/14 Python
Python3中configparser模块读写ini文件并解析配置的用法详解
2020/02/18 Python
python爬虫学习笔记之pyquery模块基本用法详解
2020/04/09 Python
高三毕业生自我鉴定
2013/12/20 职场文书
培训主管岗位职责
2014/02/01 职场文书
酒店秘书求职信范文
2014/02/17 职场文书
党的生日活动方案
2014/08/15 职场文书
大学生作弊检讨书
2014/09/11 职场文书
夫妻忠诚协议书范本
2014/11/17 职场文书
龙潭大峡谷导游词
2015/02/10 职场文书
《当代神农氏》教学反思
2016/02/23 职场文书
python自动统计zabbix系统监控覆盖率的示例代码
2021/04/03 Python