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 相关文章推荐
JS显示表格内指定行html代码的方法
Mar 31 Javascript
JS实现很实用的对联广告代码(可自适应高度)
Sep 18 Javascript
跟我学习javascript的严格模式
Nov 16 Javascript
Jquery ajax加载等待执行结束再继续执行下面代码操作
Nov 24 Javascript
基于javascript实现全屏漂浮广告
Mar 31 Javascript
Angular在模板驱动表单中自定义校验器的方法
Aug 09 Javascript
详解auto-vue-file:一个自动创建vue组件的包
Apr 26 Javascript
ES6顶层对象、global对象实例分析
Jun 14 Javascript
vue 解决form表单提交但不跳转页面的问题
Oct 30 Javascript
对vuex中getters计算过滤操作详解
Nov 06 Javascript
Vuex实现简单购物车
Jan 10 Vue.js
微信小程序实现聊天室功能
Jun 14 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提交表单时判断 if($_POST[submit])与 if(isset($_POST[submit])) 的区别
2011/02/08 PHP
php记录代码执行时间(实现代码)
2013/07/05 PHP
PHP代码优化之成员变量获取速度对比
2014/02/28 PHP
分享一段php获取linux服务器状态的代码
2014/05/27 PHP
常用参考资料(手册)下载或者链接
2006/07/22 Javascript
非常漂亮的JS+CSS图片幻灯切换特效
2013/11/20 Javascript
纯js实现遮罩层效果原理分析
2014/05/27 Javascript
jQuery CSS()方法改变现有的CSS样式表
2014/09/09 Javascript
jquery实现相册一下滑动两次的方法
2015/02/09 Javascript
如何解决ligerUI布局时Center中的Tab高度大小
2015/11/24 Javascript
全面解析Bootstrap中scrollspy(滚动监听)的使用方法
2016/06/06 Javascript
基于JavaScript实现跳转提示页面
2016/09/24 Javascript
jquery实现焦点轮播效果
2017/02/23 Javascript
JS+HTML5 canvas绘制验证码示例
2018/12/05 Javascript
仿iPhone通讯录制作小程序自定义选择组件的实现
2019/05/23 Javascript
使用layer.msg 时间设置不起作用的解决方法
2019/09/12 Javascript
python中map、any、all函数用法分析
2015/04/21 Python
Python Paramiko模块的安装与使用详解
2016/11/18 Python
python线程池(threadpool)模块使用笔记详解
2017/11/17 Python
PyQt5实现无边框窗口的标题拖动和窗口缩放
2018/04/19 Python
python numpy 显示图像阵列的实例
2018/07/02 Python
Python嵌套列表转一维的方法(压平嵌套列表)
2018/07/03 Python
Python两台电脑实现TCP通信的方法示例
2019/05/06 Python
Python+Redis实现布隆过滤器
2019/12/08 Python
使用python3 实现插入数据到mysql
2020/03/02 Python
Python如何实现定时器功能
2020/05/28 Python
CSS3 :nth-child()伪类选择器实现奇偶行显示不同样式
2013/11/05 HTML / CSS
初探CSS3中的calc()功能
2015/07/14 HTML / CSS
ivx平台开发之不用代码实现一个九宫格抽奖功能
2021/01/27 HTML / CSS
杭州-飞时达软件有限公司.net笔面试
2012/04/28 面试题
产品推广策划方案
2014/05/10 职场文书
乡镇消防安全责任书
2014/07/23 职场文书
学校联谊协议书
2014/09/16 职场文书
演讲稿之感恩老师(三篇范文)
2019/09/06 职场文书
nginx反向代理配置去除前缀案例教程
2021/07/26 Servers
css3 选择器
2022/05/11 HTML / CSS