我写的是一个公共函数,父组件直接调用
传入 localMarkdownContent 也是说流式处理过来的文字直接传给 公共组件自动转换
<template>
<div style="display: flex;">
<!-- 输入区域 -->
<textarea v-model="localMarkdownContent" placeholder="可以自行编写"></textarea>
<!-- 预览区域 -->
<div id="math" class="vue-markdown">
<!-- 使用 v-html 渲染转换后的 Markdown -->
<span v-html="get(localMarkdownContent)"></span>
</div>
</div>
</template>
引入
import MathJax from 'mathjax'; // 如果需要用到 MathJax,可以导入
import _ from 'lodash'; // 导入 lodash 库 处理防抖
下面处理父组件传过来的文字 也就是流式处理接口给的文字
data() {
return {
localMarkdownContent: this.value,
debouncedRenderMathJax: _.debounce(this.renderMathJax, 500)
};
},
props: {
value: {
type: String,
required: true
}
},
这里我用watch监听 value 如果有动作 执行 this.localMarkdownContent = newValue; // 监听外部传入的 Markdown 内容变化
watch: {
localMarkdownContent(newValue) {
this.$emit('input', newValue); // 向父组件传递更新后的 Markdown 内容
this.debouncedRenderMathJax(); // 使用防抖函数进行 MathJax 渲染
},
value(newValue) {
this.localMarkdownContent = newValue; // 监听外部传入的 Markdown 内容变化
}
},
首次进来需要先加载 库
这里我 等待2毫米 是因为有回显问题,就是编辑时候 的 回显,那时候如果自带文字,没有走流式接口也需要展示出来 转换成 数学公式
mounted() {
this.renderMathJax(); // 组件挂载时初次渲染 MathJax
},
methods: {
// 渲染 MathJax 的方法
renderMathJax() {
setTimeout(() => {
// 使用 MathJax 对指定的元素进行渲染
if (MathJax) {
MathJax.typesetPromise([document.getElementById('math')]);
} else {
console.error('MathJax not loaded');
}
}, 200);
}
MathJax.typesetPromise([document.getElementById(‘math’)]); 这行代码是直接转换 id标签里面的值 文字,注意里面不能有多余的 标签 否则失效
这样在我们通过 Vue.js 的 v-model 指令实现输入框内容与组件内部数据的双向绑定,使得用户输入能够立即反映在预览区域中。不管是用户自己输入 还是 流式接口 我们不关心 拿到文字就是执行 数学公式转换
转换玩之后最后我们渲染成html
<!-- 使用 v-html 渲染转换后的 Markdown -->
<span v-html="get(localMarkdownContent)"></span>
methods: {
// 将 Markdown 转换为 HTML 的方法
get(text) {
// 如果 text 为空或未定义,返回空字符串
if (!text) {
return '';
}
// 在每个标题前添加 <br>
const textWithLineBreaksBeforeHeaders = text.replace(/^### (.+)$/gm, '<br><h3>$1</h3>');
// 处理 ### 标题
const textWithHeaders = textWithLineBreaksBeforeHeaders.replace(/^<br>(### .+)$/gm, '<br><h3>$1</h3>');
// 用 <strong> 标签替换 ** 包裹的文本
const textWithBold = textWithHeaders.replace(/\*\*(.+?)\*\*/g, '<strong>$1</strong>');
// 用 <br> 标签替换单个换行符
const textWithBreaks = textWithBold.replace(/\n(?![\n\\])/g, '<br>');
// 用 </p><p> 标签替换两个连续的换行符
const textWithParagraphs = textWithBreaks.replace(/\n\n/g, '</p><p>');
// 在开头和结尾添加 <p> 标签,并返回处理后的文本
return `<p>${textWithParagraphs}</p>`;
},
}
最后我们实时同步到右侧 异步转换
为了提升用户体验和性能,使用 lodash 的 _.debounce 方法限制了 MathJax 的渲染频率,确保在用户输入暂停后才进行渲染操作。