2、MathJax介紹
MathJax是一款運行在瀏覽器中的開源的數學符號渲染引擎,使用MathJax可以方便的在瀏覽器中顯示數學公式,不需要使用圖片。目前,MathJax可以解析Latex、MathML和ASCIIMathML的標記語言。(Wiki)
3、步驟
3.1、引入MathJax
我們通過在index.html中加入下面語句即可引入MathJax,該語句導入的是國內的CDN。
<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.2、創建方法配置MathJax
引入MathJax之後就需要我們配置MathJax了,這是爲了讓MathJax可以通過配置的標識來識別要被轉化的數學公式。這一步我是參考了這位大佬的寫法《MathJax: 讓前端支持數學公式》的寫法,具體如下。
(1)創建globalVariable.js文件,並在裏面寫下配置方法方法。
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的配置筆記》這塊。
(2)在main.js中將globalVariable.js引入,這樣就可以在項目內任何地方都可以使用了。
import globalVariable from './components/globalVariable/globalVariable'
Vue.prototype.commonsVariable = globalVariable;
3.3、創建方法渲染公式
到了關鍵的一步了,這裏的原理就是通過傳入組件對象或者標籤id再用MathJax的window.MathJax.Hub.Queue來渲染組件來轉換公式。具體步驟如下。
(1)創建在globalVariable.js中創建渲染方法。
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.4、出現錯誤和解決方法
本來到這裏就應該結束了,但是在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