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 相关文章推荐
Safari5中alert的无限循环BUG
Apr 07 Javascript
鼠标滚轮改变图片大小的示例代码
Nov 20 Javascript
浅谈javascript 迭代方法
Jan 21 Javascript
JS操作HTML自定义属性的方法
Feb 10 Javascript
EasyUI中combobox默认值注意事项
Mar 01 Javascript
jquery拖拽效果完整实例(附demo源码下载)
Jan 14 Javascript
AngularJS中实现动画效果的方法
Jul 28 Javascript
js倒计时简单实现代码
Aug 11 Javascript
一步快速解决微信小程序中textarea层级太高遮挡其他组件
Mar 04 Javascript
JS FormData对象使用方法实例详解
Feb 12 Javascript
vue-resource post数据时碰到Django csrf问题的解决
Mar 13 Javascript
Vue+element+cookie记住密码功能的简单实现方法
Sep 20 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
关于mysql 字段的那个点为是定界符
2007/01/15 PHP
基于HTTP长连接的"服务器推"技术的php 简易聊天室
2009/10/31 PHP
php简单开启gzip压缩方法(zlib.output_compression)
2013/04/13 PHP
js有关元素内容操作小结
2011/12/20 Javascript
文字垂直滚动之javascript代码
2015/07/29 Javascript
js+canvas简单绘制圆圈的方法
2016/01/28 Javascript
JavaScript检查子字符串是否在字符串中的方法
2016/02/03 Javascript
jQuery实现的文字hover颜色渐变效果实例
2016/02/20 Javascript
基于Turn.js 实现翻书效果实例解析
2016/06/20 Javascript
webpack教程之webpack.config.js配置文件
2017/07/05 Javascript
js异步编程小技巧详解
2017/08/14 Javascript
最实用的JS数组函数整理
2017/12/05 Javascript
vue select组件的使用与禁用实现代码
2018/04/10 Javascript
详解vantUI框架在vue项目中的应用踩坑
2018/12/06 Javascript
小程序:授权、登录、session_key、unionId的详解
2019/05/15 Javascript
适合前端Vue开发童鞋的跨平台Weex的使用详解
2019/10/16 Javascript
JS箭头函数和常规函数之间的区别实例分析【 5 个区别】
2020/05/27 Javascript
vue.js 解决v-model让select默认选中不生效的问题
2020/07/28 Javascript
前端 javascript 实现文件下载的示例
2020/11/24 Javascript
[02:20]DOTA2中文配音宣传片
2013/05/22 DOTA
[03:07]完美世界DOTA2联赛PWL DAY10 决赛集锦
2020/11/11 DOTA
python开发之基于thread线程搜索本地文件的方法
2015/11/11 Python
Python基于pyCUDA实现GPU加速并行计算功能入门教程
2018/06/19 Python
对python实现合并两个排序链表的方法详解
2019/01/23 Python
Python算法的时间复杂度和空间复杂度(实例解析)
2019/11/19 Python
Python任务调度模块APScheduler使用
2020/04/15 Python
Python logging模块原理解析及应用
2020/08/13 Python
程序设计HTML5 Canvas API
2013/04/08 HTML / CSS
安德玛菲律宾官网:Under Armour菲律宾
2020/07/28 全球购物
基层党员公开承诺书
2014/05/29 职场文书
法院干警四风问题个人对照检查材料思想汇报
2014/10/07 职场文书
2014年学校党建工作汇报材料
2014/11/02 职场文书
2015年党员自我剖析材料
2014/12/17 职场文书
2015年会计工作总结范文
2015/05/26 职场文书
2015暑期社会实践个人总结
2015/07/13 职场文书
JavaScript 与 TypeScript之间的联系
2021/11/27 Javascript