vue3 使用 md-editor-v3(MdEditor)富文本插件

官方文档: https://imzbf.github.io/md-editor-v3/docs/index

安装方式

  • yarn
    yarn add md-editor-v3

  • npm
    npm install md-editor-v3

使用

toolbarsExclude 选择不需要展示的工具栏
// template
<MdEditor
    toolbarsExclude="['link', 'mermaid', 'katex', 'github']"
    v-model="text"
    @onUploadImg="onUploadImg"
    @onSave="codeSave"
>
</MdEditor>
toolbarsExclude 的属性
'bold',
  'underline',
  'italic',
  '-',
  'strikeThrough',
  'sub',
  'sup',
  'quote',
  'unorderedList',
  'orderedList',
  '-',
  'codeRow',
  'code',
  'link',
  'image',
  'table',
  'mermaid',
  'katex',
  '-',
  'revoke',
  'next',
  'save',
  '=',
  'pageFullscreen',
  'fullscreen',
  'preview',
  'htmlPreview',
  'catalog',
  'github';

// 对应功能名称
'加粗',
  '下划线',
  '斜体',
  '删除线',
  '下标',
  '上标',
  '引用',
  '无序列表',
  '有序列表',
  '行内代码',
  '块级代码',
  '链接',
  '图片',
  '表格',
  '图表',
  '公式',
  '后退一步',
  '前进一步',
  '保存',
  '页面内全屏',
  '屏幕全屏',
  '内容预览',
  'html代码预览',
  '目录',
  '源码地址';

// script 引入
import MdEditor from 'md-editor-v3';
import 'md-editor-v3/lib/style.css';
可以引入 sanitizeHtml 进行 xss 防范
// 安装
// yarn add sanitize-html
// npm install sanitize-html


<template>
  <MdEditor :sanitize="sanitize" />;
</template>

import sanitizeHtml from 'sanitize-html';

但是不知道是我使用的原因还是因为版本自身的bug 我使用 :sanitize="sanitize" 导致代码不高亮,具体的你们可以自己试试

效果图

RUNOOB 图标

完整代码
<template>
    <div class="codeShare">
        <div>
            <el-alert
                style="margin: 10px 0"
                title="信息"
                type="warning"
                description="我们不会公开你的代码,代码分享后将会给你一个访问链接,链接有效期为三天。在刷新页面前请保存好你的链接"
                show-icon
            ></el-alert>
            <el-progress v-show="isDis" :percentage="load" />
            <!-- 只读模式 :previewOnly="true" -->
            <!-- :sanitize="sanitize" 使用会导致代码不高亮 -->
            <el-button style="margin-bottom: 10px;" @click="shareCode">分享</el-button>
            <MdEditor
                toolbarsExclude="['link', 'mermaid', 'katex', 'github']"
                v-model="text"
                @onUploadImg="onUploadImg"
                @onSave="codeSave"
            >
            </MdEditor>
        </div>
    </div>
</template>

<script lang="ts">
import { shareCodeApi, onUploadImg } from '../util/api'
import {defineComponent, reactive, toRefs, onMounted} from 'vue'

import MdEditor from 'md-editor-v3';
import 'md-editor-v3/lib/style.css';
// 使用 sanitizeHtml 处理不安全的 html
import sanitizeHtml from 'sanitize-html';
import { ElMessage, ElMessageBox  } from 'element-plus';

interface shareData {
    text: string,
    load: number,
    isDis: boolean
}

export default defineComponent({
    name: "codeShare",
    components: {MdEditor},
    setup() {
        const data = <shareData> reactive({
            text: '',
            load: 0,
            isDis: false
        })

        const codeSave = (v: string):void => {
            ElMessage.info('已保存')
            localStorage.setItem('codeSave', v)
        }

        const sanitize = (html: string): string => {
            console.log(sanitizeHtml(html))
            return sanitizeHtml(html)
        }

        const href = window.location.href;
        const url = href.substring(0, href.length - 10);

        // 分享代码
        const shareCode = () => {
            if(data.text === '') {
                return ElMessage.error('为空不能分享!!!')
            }
            // @ts-ignore
            shareCodeApi({text: data.text}).then( (res) => {
                if(res.data.code === 200) {
                    ElMessageBox.alert(`你的访问链接为:<br /><a style="word-break:break-all;" target='_blank' href="${url}/getCodeShare/${res.data.data}">${url}/getCodeShare/${res.data.data}</a>`, '提示', {
                        confirmButtonText: 'OK',
                        dangerouslyUseHTMLString: true,
                    })
                    localStorage.removeItem('codeSave')
                }
            })
        }

        onMounted(() => {
            if(localStorage.getItem('codeSave')) {
                data.text = localStorage.getItem('codeSave') || ''
            }
        })

        return {
            ...toRefs(data),
            codeSave,
            sanitize, shareCode
        }
    },
    methods: {
        // 图片上传
        async onUploadImg(files: FileList, callback: (urls: string[]) => void) {
            this.load = 0
            this.isDis = true
            const res = await Promise.all(
                Array.from(files).map((file) => {
                    return new Promise((rev, rej) => {
                        const form = new FormData();
                        form.append('img', file);
                        // @ts-ignore
                        onUploadImg(form, this.onUploadProgress).then((res) => {
                            rev(res)
                        })
                    });
                })
            );

            callback(res.map((item: any) => item.data.data));
        },
        // 获取图片上传进度
        onUploadProgress(e: number) {
            this.load = e
            if(e === 100) {
                setTimeout(() => {
                    this.isDis = false
                },1000)
            }
        },


    }
});
</script>

<style scoped>
/deep/ .md {
    height: 600px!important;
}
</style>

图片上传的接口和发布富文本的接口需要自己编写,我这边是封装了后端的接口,这边你自己封装一个就可以实现上传图片还发布了。有需要也可以私信问我。提供的代码只是一个逻辑,有很多引用的代码没有提供。

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐