How to render math in Vue or Nuxt?
There are several ways to write and render beautiful math on web. However, some methods can't be directly applied to Vue.js/Nuxt.js. In this article, we will explain how to use katex
and mathjax
to render math in Vue.js/Nuxt.js.
Katex
To automatically render all math in all the pages, you need to use CDN to load katex
:
<!-- index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="icon" href="/poem-studio-favicon-black.svg">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.10/dist/katex.min.css" integrity="sha384-wcIxkf4k558AjM3Yz3BBFQUbk/zgIYC2R0QpeeYb+TwlBVMrlgLqwRjRtGZiK7ww" crossorigin="anonymous">
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.10/dist/katex.min.js" integrity="sha384-hIoBPJpTUs74ddyc4bFZSM1TVlQDA60VBbJS0oA934VSz82sBx1X7kSx2ATBDIyd" crossorigin="anonymous"></script>
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.10/dist/contrib/auto-render.min.js" integrity="sha384-43gviWU0YVjaDtb/GhzOouOXtZMP/7XUzwPTstBeZFe/+rCMvRwr4yROQP43s0Xk" crossorigin="anonymous"
onload="renderMathInElement(document.body);"></script>
<title>Manitori</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.js"></script>
</body>
</html>
If you are using Nuxt.js, then you need to change your nuxt.config.ts
:
//nuxt.config.ts
export default defineNuxtConfig({
app: {
head: {
link: [
{rel:'stylesheet', href:"https://cdn.jsdelivr.net/npm/katex@0.16.10/dist/katex.min.css", integrity:"sha384-wcIxkf4k558AjM3Yz3BBFQUbk/zgIYC2R0QpeeYb+TwlBVMrlgLqwRjRtGZiK7ww", crossorigin:"anonymous"}
],
script: [
{
defer:true,
src:"https://cdn.jsdelivr.net/npm/katex@0.16.10/dist/katex.min.js",
integrity:"sha384-hIoBPJpTUs74ddyc4bFZSM1TVlQDA60VBbJS0oA934VSz82sBx1X7kSx2ATBDIyd",
crossorigin:"anonymous"
},
{
defer:true,
src:"https://cdn.jsdelivr.net/npm/katex@0.16.10/dist/contrib/auto-render.min.js",
integrity:"sha384-43gviWU0YVjaDtb/GhzOouOXtZMP/7XUzwPTstBeZFe/+rCMvRwr4yROQP43s0Xk",
crossorigin:"anonymous",
onload:"renderMathInElement(document.body);"
},
]
}
}
})
If you want to specify the options of the renderMathInElement
function, you could call renderMathInElement
in another <script>
:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="icon" href="/poem-studio-favicon-black.svg">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.10/dist/katex.min.css" integrity="sha384-wcIxkf4k558AjM3Yz3BBFQUbk/zgIYC2R0QpeeYb+TwlBVMrlgLqwRjRtGZiK7ww" crossorigin="anonymous">
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.10/dist/katex.min.js" integrity="sha384-hIoBPJpTUs74ddyc4bFZSM1TVlQDA60VBbJS0oA934VSz82sBx1X7kSx2ATBDIyd" crossorigin="anonymous"></script>
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.10/dist/contrib/auto-render.min.js" integrity="sha384-43gviWU0YVjaDtb/GhzOouOXtZMP/7XUzwPTstBeZFe/+rCMvRwr4yROQP43s0Xk" crossorigin="anonymous"></script>
<script>
document.addEventListener("DOMContentLoaded", function() {
renderMathInElement(document.body, {
// customised options
// • auto-render specific keys, e.g.:
delimiters: [
{left: '$$', right: '$$', display: true},
{left: '$', right: '$', display: false},
{left: '\\(', right: '\\)', display: false},
{left: '\\[', right: '\\]', display: true}
],
// • rendering keys, e.g.:
throwOnError : false
});
});
</script>
<title>Manitori</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.js"></script>
</body>
</html>
Note that you'd better change document.body
to a specific area document.getElementById(Id)
, otherwise, it may cause some fatal error, see Vue - TypeError: Cannot read properties of null (reading 'insertBefore').
To render math in a specific area, you need to call renderMathInElement
separately in each page. For example:
<script lang="ts" setup>
onMounted(()=>{
nextTick(()=>{
var node = document.getElementById(Id)
document.addEventListener("DOMContentLoaded", function() {
renderMathInElement(node, {
// customised options
// • auto-render specific keys, e.g.:
delimiters: [
{left: '$$', right: '$$', display: true},
{left: '$', right: '$', display: false},
{left: '\\(', right: '\\)', display: false},
{left: '\\[', right: '\\]', display: true}
],
// • rendering keys, e.g.:
throwOnError : false
});
});
})
})
</script>
In Vue.js, you may need to asynchronously render math, so you can follow this example:
<script lang="ts" setup>
var node = document.getElementById(Id)
Promise.resolve()
.then(()=>{
nextTick(()=>{
document.addEventListener("DOMContentLoaded", function() {
renderMathInElement(node, {
// customised options
// • auto-render specific keys, e.g.:
delimiters: [
{left: '$$', right: '$$', display: true},
{left: '$', right: '$', display: false},
{left: '\\(', right: '\\)', display: false},
{left: '\\[', right: '\\]', display: true}
],
// • rendering keys, e.g.:
throwOnError : false
});
});
})
})
</script>
Mathjax
It is easy to automatically render all math using mathjax
. Like katex
, you'd better use CDN to load mathjax
:
<!-- index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="icon" href="/poem-studio-favicon-black.svg">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script type="text/javascript" id="MathJax-script" async
src="https://cdn.jsdelivr.net/npm/mathjax@4.0.0-beta.6/tex-chtml.js">
</script>
<script>
MathJax = {
tex: {
inlineMath: [['$', '$'], ['\\(', '\\)']]
}
};
</script>
<title>Manitori</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.js"></script>
</body>
</html>
If you are using Nuxt.js, then change your nuxt.config.ts
like this:
//nuxt.config.ts
export default defineNuxtConfig({
app: {
head: {
script: [
{
type: "text/javascript",
id: "MathJax-script",
async: true,
src: "https://cdn.jsdelivr.net/npm/mathjax@4.0.0-beta.6/tex-chtml.js",
},
{
innerHTML:
"MathJax = {tex: {inlineMath: [['$', '$'],['$$', '$$']]}};",
},
]
})
However, in Vue.js you also need to asynchronously render math using mathjax
, otherwise, The rendered math formula will revert back to original text. You can call MathJax.typesetPromise()
to achieve this. For example:
<script lang="ts" setup>
Promise.resolve()
.then(()=>{
nextTick(() => {
MathJax.typesetPromise();
});
})
</script>
Or you could use setTimeout
instead of nextTick
:
setTimeout(() => {
MathJax.typesetPromise();
}, 3000);
Following our methods, you can easily integrate Vue.js/Nuxt.js with katex and mathjax😄!
0 人喜欢
There is no comment, let's add the first one.