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检查日期格式的函数[比较全]
Oct 17 Javascript
基于Jquery的仿照flash放大图片效果代码
Mar 16 Javascript
使用js在页面中绘制表格核心代码
Sep 16 Javascript
JS判断对象是否存在的10种方法总结
Dec 23 Javascript
简单谈谈node.js 版本控制 nvm和 n
Oct 15 Javascript
node.js+express制作网页计算器
Jan 17 Javascript
AngularJS中的API(接口)简单实现
Jul 28 Javascript
js获取浏览器高度 窗口高度 元素尺寸 偏移属性的方法
Nov 21 Javascript
JS实现简易的图片拖拽排序实例代码
Jun 09 Javascript
浅谈vue2 单页面如何设置网页title
Nov 08 Javascript
利用JQUERY实现多个AJAX请求等待的实例
Dec 14 jQuery
layui的布局和表格的渲染以及动态生成表格的方法
Sep 18 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之Smarty入门
2007/01/04 PHP
利用Memcached在php下实现session机制 替换PHP的原生session支持
2010/08/21 PHP
php.ini中date.timezone设置分析
2011/07/29 PHP
php中的常用魔术方法总结
2013/08/02 PHP
Yii框架调试心得--在页面输出执行sql语句
2014/12/25 PHP
PHP中静态变量的使用方法实例分析
2016/12/01 PHP
PHP实现的下载远程文件类定义与用法示例
2017/07/05 PHP
php遍历目录下文件并按修改时间排序操作示例
2019/07/12 PHP
laravel框架中控制器的创建和使用方法分析
2019/11/23 PHP
jQuery调用WebService的实现代码
2011/06/19 Javascript
js模拟select下拉菜单控件的代码
2013/05/08 Javascript
简单的代码实现jquery定时器
2013/11/17 Javascript
javascript的日期对象、数组对象、二维数组使用说明
2014/12/22 Javascript
Nodejs学习笔记之NET模块
2015/01/13 NodeJs
JavaScript Window浏览器对象模型方法与属性汇总
2015/04/20 Javascript
jQuery插件Slider Revolution实现响应动画滑动图片切换效果
2015/06/05 Javascript
原生js实现自由拖拽弹窗代码demo
2016/06/29 Javascript
AngularJS表格样式简单设置方法示例
2017/03/03 Javascript
常用的 JS 排序算法 整理版
2018/04/05 Javascript
jQuery.parseJSON()函数详解
2019/02/28 jQuery
layui清除radio的选中状态实例
2019/11/14 Javascript
原生JS实现顶部导航栏显示按钮+搜索框功能
2019/12/25 Javascript
js实现从右往左匀速显示图片(无缝轮播)
2020/06/29 Javascript
OpenLayer学习之自定义测量控件
2020/09/28 Javascript
Python文件及目录操作实例详解
2015/06/04 Python
python实现多层感知器
2019/01/18 Python
Flask和pyecharts实现动态数据可视化
2020/02/26 Python
社区版pycharm创建django项目的方法(pycharm的newproject左侧没有项目选项)
2020/09/23 Python
使用postMessage让 iframe自适应高度的方法示例
2019/10/08 HTML / CSS
美国购买新书和二手书网站:Better World Books
2018/10/31 全球购物
实习自我评价怎么写
2013/12/02 职场文书
幼儿园教师考核评语
2014/12/31 职场文书
拿破仑传读书笔记
2015/07/01 职场文书
JDBC连接的六步实例代码(与mysql连接)
2021/05/12 MySQL
学习nginx基础知识
2021/09/04 Servers
Vue h函数的使用详解
2022/02/18 Vue.js