Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

mathjax + vue not rerendering equations

I'm building a vue application and I want to use MathJax to render equations. I can get the equations to render when the component is mounted but I can't get the equations to rerender at a later point.

I made a code sandbox example to demonstrate this. Try to change the latex equation in the input and nothing changes even though the console shows the watcher is running.

Can someone please explain to me what I am doing wrong?

I added mathjax via cdn in the head of index.html with the following config

<script type="text/x-mathjax-config">
  MathJax.Hub.Config({
    tex2jax: {
      inlineMath: [['$','$'],['\\(','\\)']],
    }
  });
</script>
<script type="text/javascript" async src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/MathJax.js?config=TeX-AMS_CHTML"></script>

and here is the code in my app component

<template>
  <div id="app">
    <input v-model="latex"/><br>
    <div>{{latex}}</div>
  </div>
</template>

<script>
export default {
  name: "App",
  data() {
    return {
      latex: '$$\\frac{a}{b}$$'
    }
  },
  methods: {
    reRender() {
      if(window.MathJax) {
        console.log('rendering mathjax');
        window.MathJax.Hub.Queue(["Typeset", window.MathJax.Hub], () => console.log('done'));
      }
    }
  },
  mounted() {
    this.reRender();
  },
  watch: {
    latex: function() {
      console.log('data changed')
      this.reRender();
    }
  }
};
</script>
like image 265
Devin Crossman Avatar asked Oct 03 '18 22:10

Devin Crossman


1 Answers

I am able to make it work by adding 2 things.

https://codesandbox.io/s/x2mlq38m4z

  1. add key to the div. key is an indicator for virtual DOM. When key is the same, Vue may reuse the same div element. When key change, Vue will render a completely new DOM element, which is helpful when you want to apply 3rd party library's code (MathJax) to the DOM from scratch.

    <div :key="latex">{{latex}}</div>

  2. use $nextTick so that the rerender happens after the DOM have updated.

like this

  watch: {
    latex: function() {
      console.log('data changed');
      this.$nextTick().then(()=>{
        this.reRender();
      });
    }
  }
like image 101
Jacob Goh Avatar answered Oct 18 '22 11:10

Jacob Goh