程序员

vue使用Katex渲染数学公式

2020-09-29  本文已影响0人  potenstop

版本说明

vue:2.x
katex: 0.11.x

安装

npm install katex

新建渲染的组件AutoKatex.vue

<template>
  <div v-html="htmlData" :style="{display: isLineFeed?'block' : 'inline'}">
  </div>
</template>

<script lang="ts">
import { Component, Prop, Vue, Watch } from 'vue-property-decorator'
import katex from 'katex'
import 'katex/dist/katex.min.css'
import { JSHelperUtil, StringUtil } from 'papio-h5'

@Component
export default class AutoKatex extends Vue {
  private name = 'AutoKatex'
  // 带有公式的源文本
  @Prop({ default: '' }) readonly data!: string;
  // 是否占用一行
  @Prop({ default: true }) readonly isLineFeed!: boolean;
  @Prop({ default: '$$' }) readonly delimiters!: string;
  private htmlData = ''

  private created () {
    this.katexRender()
  }

  @Watch('data')
  private dataChanged () {
    this.katexRender()
  }

  private katexRender () {
    const data = this.data
    const delimitersLength = this.delimiters.length
    if (StringUtil.isEmpty(data)) {
      return
    }
    let pos = data.indexOf(this.delimiters)
    const positions = []
    while (pos > -1) {
      positions.push(pos)
      pos = data.indexOf(this.delimiters, pos + delimitersLength)
    }
    let htmlData = ''
    if (positions.length <= 1) {
      // 没有公式
      htmlData = this.getSpanHtml(data)
    } else {
      // 存在公式
      // 处理index=1
      htmlData += this.getSpanHtml(data.substring(0, positions[0]))
      // 遍历下标数据
      for (let index = 1; index <= positions.length - 1; index++) {
        const current = positions[index]
        // 下标为奇数 则开始 偶数数为结束
        if (index % 2 !== 0) {
          const d = katex.renderToString(data.substring(positions[index - 1] + delimitersLength, current), { throwOnError: false })
          htmlData += d
        } else {
          htmlData += this.getSpanHtml(data.substring(positions[index - 1] + delimitersLength, current))
        }
      }
      htmlData += this.getSpanHtml(data.substring(positions[positions.length - 1] + delimitersLength))
    }
    this.htmlData = htmlData
  }
  private getSpanHtml (str): string {
    // 换行替换为</br>
    return `<span>${str}</span>`
  }
}
</script>

<style scoped>

</style>

组件参数说明

使用方法

<template xmlns:v-katex="http://www.w3.org/1999/xhtml">
  <div>
    <input v-model:value="inputValue"/>
    <auto-katex :data="inputValue"></auto-katex>
  </div>
</template>

<script lang="ts">
import { Component, Vue, Watch } from 'vue-property-decorator'
import AutoKatex from '@/components/katex/AutoKatex.vue'

@Component({
  components: {
    AutoKatex
  }
})
export default class CourseTopicEdit extends Vue {
  private inputValue: string = ''
}
</script>
<style scoped>
</style>

使用效果

演示图.png
上一篇下一篇

猜你喜欢

热点阅读