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文本改变触发事件如聚焦事件、失焦事件
Jan 15 Javascript
jQuery实现带滚动导航效果的全屏滚动相册实例
Jun 19 Javascript
js判断手机号运营商的方法
Oct 23 Javascript
纯javascript响应式树形菜单效果
Nov 10 Javascript
js实现文字垂直滚动和鼠标悬停效果
Dec 31 Javascript
JavaScript与ActionScript3两者的同性与差异性
Sep 22 Javascript
jQuery 特性操作详解及实例代码
Sep 29 Javascript
JS获取填报扩展单元格控件的值的解决办法
Jul 14 Javascript
浅谈在vue项目中如何定义全局变量和全局函数
Oct 24 Javascript
使用Node.js实现一个多人游戏服务器引擎
Mar 13 Javascript
ES6 Object方法扩展的应用实例分析
Jun 25 Javascript
微信小程序 wx:for遍历循环使用实例解析
Sep 09 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常用函数小技巧
2008/09/11 PHP
php写的AES加密解密类分享
2014/06/20 PHP
分享PHP计算两个日期相差天数的代码
2015/12/23 PHP
PHP copy函数使用案例代码解析
2020/09/01 PHP
jquery实现的导航固定效果
2014/04/28 Javascript
28个常用JavaScript方法集锦
2015/01/14 Javascript
js判断主流浏览器类型和版本号的简单实现代码
2016/05/26 Javascript
fckeditor部署到weblogic出现xml无法读取及样式不能显示问题的解决方法
2017/03/24 Javascript
关于javascript sort()排序你可能忽略的一点理解
2017/07/18 Javascript
JavaScript定义函数的三种实现方法
2017/09/23 Javascript
详解js跨域请求的两种方式,支持post请求
2018/05/05 Javascript
JS实现图片上传多次上传同一张不生效的处理方法
2018/08/06 Javascript
Vuex 使用及简单实例(计数器)
2018/08/29 Javascript
深入浅析Vue.js 中的 v-for 列表渲染指令
2018/11/19 Javascript
vue-router实现编程式导航的代码实例
2019/01/19 Javascript
JavaScript变速动画函数封装添加任意多个属性
2019/04/03 Javascript
JS通过ajax + 多列布局 + 自动加载实现瀑布流效果
2019/05/30 Javascript
Js代码中的span拼接问题解决
2019/11/22 Javascript
通过实例了解Javascript柯里化流程
2020/03/03 Javascript
基于jquery实现彩色投票进度条代码解析
2020/08/26 jQuery
python线程池threadpool实现篇
2018/04/27 Python
Python根据已知邻接矩阵绘制无向图操作示例
2018/06/23 Python
python aiohttp的使用详解
2019/06/20 Python
django-allauth入门学习和使用详解
2019/07/03 Python
使用python实现离散时间傅里叶变换的方法
2019/09/02 Python
python绘制彩虹图
2019/12/16 Python
pytorch实现mnist分类的示例讲解
2020/01/10 Python
Python接口开发实现步骤详解
2020/04/26 Python
三个Unix的命令面试题
2015/04/12 面试题
30年同学聚会感言
2014/01/30 职场文书
岗位竞聘演讲稿范文
2014/04/24 职场文书
大学新闻系求职信
2014/06/03 职场文书
2015年调度员工作总结
2015/04/30 职场文书
2015年教师见习期工作总结
2015/05/20 职场文书
初中语文教学研修日志
2015/11/13 职场文书
mysql函数之截取字符串的实现
2022/08/14 MySQL