Vue项目中在md-editor-v3工具栏中添加自定义工具

以NEU小站中的“选择课程”工具为例

效果

NEU小站项目(基于Vue3)中,我在md-editor-v3的工具栏中实现了一个“选择课程”工具,可以帮助用户搜索并选择相应的课程,然后插入一个包含课程id的组件标签。效果:

实现

首先我们需要在组件处注册一个自定义工具的模板,注意使用#defToolbars,设置好图标、说明文字和点击事件,参考此处

 1<div class="editor-container">
 2<MdEditor
 3    v-model="formData.content"
 4    ref="markdownEditor"
 5    :theme="editorTheme"
 6    :toolbars="editorToolbars"
 7    language="zh-CN"
 8    preview-theme="github"
 9    :placeholder="editorPlaceholder"
10    @onUploadImg="handleImageUpload"
11>
12    <!-- 自定义工具 -->
13    <template #defToolbars>
14        <span class="md-editor-toolbar-item" title="添加课程卡片" @click="chooseCourse">
15        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" width="20" height="24" stroke-width="1.1">
16            <path d="M22 9l-10 -4l-10 4l10 4l10 -4v6"></path>
17            <path d="M6 10.6v5.4a6 3 0 0 0 12 0v-5.4"></path>
18        </svg>
19        </span>
20    </template>
21</MdEditor>
22</div>
23
24<script>
25import MdEditor from 'md-editor-v3';
26import 'md-editor-v3/lib/style.css';
27export default {
28    components: {
29        MdEditor
30    }
31}
32</script>

然后,在data()editorToolbars中添加自定义工具的配置,这里非常重要,需要用0来表示自定义工具的位置。如果有多个自定义工具,则以此类推0、1、2…,类似数组下标。

1editorToolbars: [
2    'bold', 'italic', 'strikethrough', 'title', 'sub', 'sup', 'quote', 'unordered-list', 
3    'ordered-list', 'link', 'image', 'table', 'code-block', 'inline-code', 'preview',
4    'fullscreen', '-', 'revoke', 'next', '-', 0
5],

这样我们的自定义图标就会出现在工具栏的对应位置。现在完成chooseCourse方法。方法内的逻辑自行定义,但是我们最终的操作一般是需要在编辑器中插入一段文本,所以需要使用编辑器提供的insert方法。

参考insert API,文档如下:

 1/**
 2 * @params selectedText 选中的内容
 3 */
 4editorRef.value?.insert((selectedText) => {
 5  /**
 6   * @return targetValue    待插入内容
 7   * @return select         插入后是否自动选中内容,默认:true
 8   * @return deviationStart 插入后选中内容鼠标开始位置,默认:0
 9   * @return deviationEnd   插入后选中内容鼠标结束位置,默认:0
10   */
11  return {
12    targetValue: `${selectedText}`,
13    select: true,
14    deviationStart: 0,
15    deviationEnd: 0,
16  };
17});

说明我们需要返回一个对象,对象中的targetValue就是我们最终插入的内容。这里给个简单的例子:

1chooseCourse() {
2    const id = 3;
3    this.$refs.markdownEditor?.insert((selectedText) => {
4        return {
5            targetValue: `<CourseCard id="${id}" />\n`
6        }
7    })
8}

这样,点击这个工具,就会在编辑器中插入<CourseCard id="3" />。具体的查询逻辑可以自行实现,这里不再赘述。