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

相關文章
相關標籤/搜索