Vue使用MathJax动态识别数学公式

本人菜鸟一名,若有错误,还请见谅。javascript

一、前言

  最近公司的一个项目需求是在前端显示Latex转化的数学公式,通过不断的百度和测试已基本实现。如今此作一个记录。html

二、MathJax介绍

  MathJax是一款运行在浏览器中的开源的数学符号渲染引擎,使用MathJax能够方便的在浏览器中显示数学公式,不须要使用图片。目前,MathJax能够解析Latex、MathML和ASCIIMathML的标记语言。(Wiki)前端

三、步骤

  3.一、引入MathJax

    咱们经过在index.html中加入下面语句便可引入MathJax,该语句导入的是国内的CDN。vue

<script type="text/javascript" async src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/MathJax.js?config=TeX-MML-AM_CHTML"></script>

  3.二、建立方法配置MathJax

    引入MathJax以后就须要咱们配置MathJax了,这是为了让MathJax能够经过配置的标识来识别要被转化的数学公式。这一步我是参考了这位大佬的写法《MathJax: 让前端支持数学公式》的写法,具体以下。java

    (1)建立globalVariable.js文件,并在里面写下配置方法方法。ios

let isMathjaxConfig = false;//用于标识是否配置 const initMathjaxConfig = () => { if (!window.MathJax) { return; } window.MathJax.Hub.Config({ showProcessingMessages: false, //关闭js加载过程信息
        messageStyle: "none", //不显示信息
        jax: ["input/TeX", "output/HTML-CSS"], tex2jax: { inlineMath: [["$", "$"], ["\\(", "\\)"]], //行内公式选择符
            displayMath: [["$$", "$$"], ["\\[", "\\]"]], //段内公式选择符
            skipTags: ["script", "noscript", "style", "textarea", "pre", "code", "a"] //避开某些标签
 }, "HTML-CSS": { availableFonts: ["STIX", "TeX"], //可选字体
            showMathMenu: false //关闭右击菜单显示
 } }); isMathjaxConfig = true; //配置完成,改成true }; export default { isMathjaxConfig, initMathjaxConfig, }

  这一步其实也可使用直接配置的方法,这里就不记录了,具体能够看《前端整合MathjaxJS的配置笔记》这块。ajax

  (2)在main.js中将globalVariable.js引入,这样就能够在项目内任何地方均可以使用了。axios

import globalVariable from './components/globalVariable/globalVariable' Vue.prototype.commonsVariable = globalVariable;

  3.三、建立方法渲染公式

  到了关键的一步了,这里的原理就是经过传入组件对象或者标签id再用MathJax的window.MathJax.Hub.Queue渲染组件来转换公式。具体步骤以下。浏览器

  (1)建立在globalVariable.js中建立渲染方法。app

const MathQueue = function (elementId) { if (!window.MathJax) { return; } window.MathJax.Hub.Queue(["Typeset", window.MathJax.Hub, document.getElementById(elementId)]); }; export default { Header, isMathjaxConfig, initMathjaxConfig, MathQueue, }

  这一步不必定用传入id的方式,也能够传入标签name用getElementByName来获取组件对象。

  (2)再须要渲染的页面中调用方法便可。当vue数据改变的时候,咱们使用$nextTick等待组件数据渲染完成后,再将组件id传入方法中,让mathjax来渲染公式。

<template>
    <div> 
       <div id="question-id">
            <div class="swappy-radios" >
                <div name="titleDiv">
                    <h3> 题目:{{this.questionToOptions.Question.body}}</h3> //这里的questionToOptions.Question.body传入的就是Latex公式
                </div>
            </div>
        </div>
    </div>
</template>

<script> export default { props: { value: {} }, data() { return { rawHtml:'', heightString: 'height: 500px;', questionToOptions: this.value, answer: '', imgIndex: 0, }; }, methods: {
 }, watch: { //监听prop传的value,若是父级有变化了,将子组件的myValue也跟着变,达到父变子变的效果
            //这里看需求,若不使用监听,直接放在axios请求方法中也是能够的
 value(value) { // titleDiv
                this.questionToOptions = value; this.answer = ''; this.$nextTick(function () { //这里要注意,使用$nextTick等组件数据渲染完以后再调用MathJax渲染方法,要否则会获取不到数据
                    if(this.commonsVariable.isMathjaxConfig){//判断是否初始配置,若无则配置。
                        this.commonsVariable.initMathjaxConfig(); } this.commonsVariable.MathQueue("question-id");//传入组件id,让组件被MathJax渲染
 }) }, answer(newVal) { this.$emit('trouble', newVal) } }, mounted() { } } </script>

 

  效果图:

  

 

 

 

  3.四、出现错误和解决方法

  原本到这里就应该结束了,可是在value数据连续改变的状况状况下MathJax渲染过得数据会不断堆积,形成错误。状况以下:

  第一次改变:

  

 

   第二次改变:

  

 

   对于这个错误我没有找到一个好的解释,如有知道的大佬还请指出,多谢了。

  我本身最后猜想是MathJax对于同一个组件渲染不是以刷新的方式,而是在上一次渲染的基础上添加数据进行渲染。因此我想到了,在下次渲染以前先将上一个组件内部带有数学公式清空,而后再进行渲染。具体方式以下:

<template>
    <div> 
       <div id="question-id">
            <div class="swappy-radios" >
                <div name="titleDiv">
                    <div v-html="rawHtml"></div>//这里改成用v-html,经过html字符串来每次生成html代码,从而达到刷新组件的效果。
                </div>
            </div>
        </div>
    </div>
</template>

<script> export default { props: { value: {} }, data() { return { rawHtml:'', heightString: 'height: 500px;', questionToOptions: this.value, answer: '', imgIndex: 0, }; }, methods: { }, watch: { value(value) { // titleDiv
                this.questionToOptions = value; this.rawHtml = '<h3>题目:'+this.questionToOptions.Question.body +'</h3>';//将公式转化为html字符串存入。 this.answer = ''; this.$nextTick(function () { if(this.commonsVariable.isMathjaxConfig){ this.commonsVariable.initMathjaxConfig(); } this.commonsVariable.MathQueue("question-id"); }) }, answer(newVal) { this.$emit('trouble', newVal) } }, mounted() { } } </script>

  这样就能够避免数据堆积的错误了。

  效果图以下

  第一次改变:

  

   第二次改变:

  

   

  ok,这样就修改完成了。

参考文章:https://www.jianshu.com/p/03a7bb984a1d

     https://www.linpx.com/p/front-end-integration-mathjaxjs-configuration.html

相关文章
相关标签/搜索