·

Vue或Nuxt中如何渲染数学公式?

发布时间:2024-06-06 16:13:27阅读量:907
专业文章
转载请注明来源

在网页上,有很多种方法可以渲染漂亮的数学公式。但是这些方法基本上不能直接应用于Vue.js或者Nuxt.js。在本文中,我们将分别说明如何在Vue.js或者Nuxt.js中使用katexmathjax渲染数学公式。

Katex

想要自动渲染所有页面上的数学公式,你需要使用CDN来加载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>

如果你使用的是Nuxt.js,那么你需要修改你的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);"
        },
       ]
    }
  }

})

如果你需要更改renderMathInElement函数的选项,你可以在另一个<script>标签中调用renderMathInElement

<!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>

需要注意的是,直接使用document.body可能会导致一些关键性错误,见Vue - TypeError: Cannot read properties of null (reading 'insertBefore')。因此,建议将document.body 改为一个特定的渲染区域document.getElementById(Id) ,不过这样的话,你需要每一页都分别调用一次renderMathInElement

<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>

在Vue.js中,你估计需要异步渲染数学公式,因此可以根据以下示例写:

<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

mathjax来自动渲染数学公式,比katex要简单得多。跟katex一样,你最好使用CDN来加载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>

如果你使用的是Nuxt.js,那么在你的nuxt.config.ts 中添加如下代码:

//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: [['$', '$'],['$$', '$$']]}};",
        },
      ]
})

然而在Vue.js中,使用mathjax,你也需要异步渲染数学公式。不然,所有渲染的数学公式都会重新变回原样。为此,你需要使用MathJax.typesetPromise()

<script lang="ts" setup>
Promise.resolve()
.then(()=>{
  nextTick(() => {
    MathJax.typesetPromise();
  });
})
</script>

或者你可以使用setTimeout来替代nextTick:

setTimeout(() => {
  MathJax.typesetPromise();
}, 3000);

根据上面的做法,你就可以轻松在Vue.js或Nuxt.js中整合katex和mathjax啦😄!

0 人喜欢

评论区

暂无评论,来发布第一条评论吧!

弦圈热门内容

一个关于定义域光滑不变量的问题

我的提问:定理 22.3(定义域的光滑不变量)令$U \subset\mathbb{R}^n$为一个开子集,$S \subset\mathbb{R}^n$为一个任意子集,并且$f : U \rightarrow S$是一个微分同胚。那么$S$在$\mathbb{R}^n$中是开集。我无法理解为何集合$S$在$\mathbb{R}^n$中并不是自动开的。映射$f$是一个微分同胚,这意味着它在两个方向都是连续的,所以$S$是开的。回答:首先你所知道的是$U$中的开集$V$满足:$f(V)$在$S$中开,不是$f(V)$在$\mathbb{R}^n$中开。所以$f(U)=S$是在$S$中开。那个推断是说接着$f(U)=S$自动在$\mathbb R^n$中开,这是不一样的并且不是自动的。它需要证明。PS:这里说的是拓扑学中关于开集的一个重要盲点,即开集是相对的。尤其是考虑某个拓扑空间中的子集,要弄清楚究竟是在子集内开,还是在全空间内开。

弦圈更新日志:关于智力值和金币

今天我完善了弦圈的签到功能,并将其放置于首页。接着我新增了智力值和金币这两个用户特征,算是完成之前的计划 10月底至11月初,弦圈功能更新:上传附件。接着,我还顺带完善了一下附件上传功能。智力值其实就是用户的经验值,初始值是100,通过每天签到即可获得10点。而金币呢,看起来是付费的,但其实金币是免费获得的。我的设想是,每天签到获得智力值,而智力值可以存在小金库中产生金币,像钱存在银行中有利息一样,这就是所谓知识的力量😇!书中自有黄金屋!目前小金库还没来得急写,之后相关功能会陆续补上。并且以前的一些功能,还会进一步完善和优化,提高网站的使用体验。

代数几何教皇Grothendieck经典著作:代数几何原理EGA法语原版全系列(1)

熟知Grothendieck都知道,他有代数几何三部曲:EGA、SGA、FGA。其中知名度最高的无疑是EGA和SGA,他们可以说是代数几何的圣经,是无数重要且知名概念和理论的源头。相较于SGA,EGA受众可能更大些,看的人也更多些。毕竟SGA只是讨论班,而EGA则相当于代数几何的百科词典。在上帖中,我已经分享了SGA法语原版全系列(链接:代数几何教皇Grothendieck经典著作:代数几何讨论班法语原版全系列),EGA法语全系列相较于SGA在当年要好收集一些,但也不容易。在当时已经有中文翻译版了,还有英文版翻译,我都看过,最后觉得还是法语版最好,英文版次之。因为有些术语翻译成中文,真的不太好理解,见英语不好,读不懂英文数学教材怎么办?不过之后我还是会把中文翻译版和英文翻译版都发出来。接着我还发一发Grothendieck的其他著作,包括收获与播种、伽罗华长征、一个纲领的提纲(Esquisse d'un Programme)等。EGA有四系列,为EGA 1-4,但总共分为8册书,EGA 3有两本,EGA 4有四本。由于文件较大,我分成两贴将这些东西发完。本贴先发EGA 1-3,需要下载 ...

把加法与乘法结构拆掉再复原?望月新一如何引发代数几何变革

据《朝日新闻》,望月新一关于ABC猜想的论文可能将要发表,审核它的期刊是《数理解析研究所公刊》(PRIMS)。媒体对此的报道大抵聚焦在两点上:一是这个期刊就是他的工作单位主办的,一是这个论文几乎无人能懂。作为一个数学研究者,我个人并不担心望月新一的利益冲突问题,不但因为数学界有一套相当完备的系统用以避免利益冲突,在选定编辑和审稿人时有良好的避嫌标准,更重要的是:他没有动机。他已经功成名就,不需要什么文章。数学这种东西,对就对,错就错,不存在编数据或者实验造假,一切细节都在文章里。要是错了,无论强行发表在什么期刊上,也终有一天会被发现,而一发现就无可抵赖,只能重新修补。但是他的理论绝不仅仅是一个“几乎无人能懂”的怪物而已。它所试图解决的根本数学问题,它背后的当代数学界的面貌,它反映出的做数学研究是怎样的状态,这里面还有太多的故事并不是、也不应该是只有几个人能懂。甚至也许可以说,这些故事能让人直观地感受到:现代数学是什么。破题望月新一的研究领域,是所谓的“远阿贝尔几何学”。如果一句话解释这个领域的话,我只能这样写:有理数的绝对伽罗华群,以至任意代数簇的平展基本群,它们“远离阿贝尔”的部分, ...

将反向传递看成函子:强化学习的一个复合视角

这篇文章是数学家与计算机科学家合作写的,将范畴论应用于人工智能的强化学习。本文表示,强化学习算法与强化学习算法的复合,还是一个强化学习算法,因而所有强化学习算法构成一个范畴$\textrm{Learn}$。然后在$\textrm{Learn}$里考虑神经网络,并证明在一般情况下,梯度下降也是复合的。如果对纯数学理论,在计算机或者AI有什么应用感兴趣的人,可以看看。我当时下这篇文章,也是好奇代数领域在AI方面有啥应用,其实当时已经知道有个叫热带几何(Tropical Geometry)的领域,就是代数几何在计算机的应用。因为当时AI就很火,但AI可解释性需要很多数学来解决,他们解决不了,所以我留着这篇文章也是打算之后写篇类似的AI应用的文章。

Tammo Tom Dieck代数拓扑教材

EMS出版的代数拓扑教材Algebraic Topology,作者是Tammo Tom Dieck。本教材相较于Hatcher的书,没有那么太多的插图,并且内容更加抽象。本书知识密度高,内容精炼简洁,没有过多的废话。很适合有一定代数基础,且喜欢直接切入主题,快速学习的人。对于还未入门的小白而言,这本书不太适合作为代数拓扑的入门教材。我高中的时候就在看这本教材,但总在一些地方无法彻底理解。但这本教材吸引我的地方,一是它的内容涵盖面够广,并且知识密度够高,能够让我短时间内掌握代数拓扑方面的基础知识;二是它的描述更加的抽象,并且语句简洁明了、容易理解,很符合我的口味(这也是我当时选择代数几何的原因)。关于本教材与其他代数拓扑教材更具体、更专业的对比,请看Algebraic Topology I: 对教材跟概念的一些论述。

Algebraic Topology I: 对教材跟概念的一些论述

关键词:Homotopy, Homology, Groupoid, Foundamental Group, Van Kampen Theorem, Covering Space, Covering Projection, Fibration with unique path lifting, Cofibration.Tammo tom Dieck 在他的代数拓扑教材中写了非常漂亮的前言,在点出代数拓扑精髓的同时还包含一些形而上学的哲思,并且简略地介绍了代数拓扑里面的两个核心词汇,同伦(homotopy) 跟同调 (homology)。我简要地部分翻译如下:代数拓扑是连续数学跟离散数学交相辉映的学科。在连续数学里面,我们用拓扑空间和连续映射这样普遍的形式语言将其公理化。而离散数学则是被我们用来表达代数和组合概念的。在数学语言中,我们用实数来概念化连续形式,但我们建立实数时却是要用到整数。下面举个例子,我们直觉地认为时间是一个连续的没有间断的流动过程,是由一系列不停止的瞬间后继构成的。但在实践中,我们却使用被定义为有周期性的离散模型工具跟自然过程。同样地,我们意识到空间是一个连续体,但我们 ...