关于前端:来康康vue3环境下的markdown编辑器mdeditorv3吧支持tsx暗黑模式哦

46次阅读

共计 3613 个字符,预计需要花费 10 分钟才能阅读完成。

开发背景

这所有都源于在开发 vue3-admin 的 demo 内容时,没有适合的编辑器组件。

阐明

仅反对 vue3 我的项目下应用,应用 jsx 语法开发,反对在 tsx 我的项目应用。为了减小插入,没有应用 less.modifyVars 办法来切换主题,而采纳了替换 class 名称的形式。

代码仓库:md-editor-v3

性能一览

  1. 快捷插入内容工具栏、编辑器浏览器全屏、页面内全屏等;
  2. 内置的红色主题和暗黑主题,反对绑定切换;
  3. 反对快捷键插入内容;
  4. 反对应用 prettier 格式化内容(应用 CDN 形式引入,只反对格式化 md 内容,可在代码内设置敞开);
  5. 反对多语言,反对自行扩大语言;
  6. 反对复制粘贴上传图片;

更多功能待后续更新,若有想要的性能未开发,请留言~

预览图

默认模式下:

暗黑模式下:

在线预览

主题追随返回 vue3-admin 尝试~~

编辑器主页演示没开发完~~~

apis

留神在 jsx 下需应用 modelValue 配合 onChange 办法实现数据绑定,在 vue 模板语法下,能够间接应用 v-modal 指令~

props

名称 类型 默认值 阐明
modelValue String md 编辑内容,vue 模板反对双向绑定(v-model=”value”)
editorClass String 编辑器最外层款式
hljs Object null 我的项目中应用到了 highlight,可将实例间接传递,生产环境则不会申请 CDN,须要手动导入反对的高亮代码款式
highlightJs String highlight.js highlightJs CDN
highlightCss String atom-one-dark 预览高亮代码款式
historyLength Number 10 最大记录操作数(太大会占用内存)
pageFullScreen Boolean false 浏览器内全屏
preview Boolean true 预览模式
htmlPreview Boolean false html 预览
language String ‘zh-CN’ 内置中英文(‘zh-CN’,’en-US’),可自行扩大其余语言,同时可笼罩内置的中英文
languageUserDefined Array [{key: StaticTextDefaultValue}] 通过这里扩大语言,批改 language 值为扩大 key 即可,类型申明可手动导入
toolbars Array [all] 选择性展现工具栏,可选内容如下[toolbars]
prettier Boolean true 是否启用 prettier 优化 md 内容
prettierCDN String standalone
prettierMDCDN String parser-markdown
editorName String ‘editor’ 当在同一页面搁置了多个编辑器,最好提供该属性以区别某些带有 ID 的内容

[toolbars]

[
  'bold',
  'underline',
  'italic',
  'strikeThrough',
  'title',
  'sub',
  'sup',
  'quote',
  'unorderedList',
  'orderedList',
  'codeRow',
  'code',
  'link',
  'image',
  'table',
  'revoke',
  'next',
  'save',
  'pageFullscreen',
  'fullscreen',
  'preview',
  'htmlPreview',
  'github'
];

自定义语言,须要替换的内容如下(某些字段若不被动提供,可能会造成页面不美观):

[StaticTextDefaultValue]

export interface StaticTextDefaultValue {
  toolbarTips?: ToolbarTips;
  titleItem?: {
    h1?: string;
    h2?: string;
    h3?: string;
    h4?: string;
    h5?: string;
    h6?: string;
  };
  linkModalTips?: {
    title?: string;
    descLable?: string;
    descLablePlaceHolder?: string;
    urlLable?: string;
    UrlLablePlaceHolder?: string;
    buttonOK?: string;
    buttonUpload?: string;
  };
}

事件绑定

名称 入参 阐明
onChange v:String 内容变动事件(以后与 textareoninput事件绑定,每输出一个单字即会触发)
onSave v:String 保留事件,快捷键与保留按钮均会触发
onUploadImg files:FileList, callback:Function 上传图片事件,弹窗会期待上传后果,务必将上传后的 urls 作为 callback 入参回传

快捷键

次要以 CTRL 搭配对应性能英文单词首字母,抵触项增加SHIFT,再抵触替换为ALT

键位 性能 阐明 开发标记
CTRL + S 保留 触发编辑器的 onSave 回调
CTRL + B 加粗 ** 加粗 **
CTRL + U 下划线 <u> 下划线 </u>
CTRL + I 斜体 * 斜体 *
CTRL + 1-6 1-6 级题目 # 题目
CTRL + ↑ 上角标 <sup> 上角标 </sup>
CTRL + ↓ 下角标 <sub> 下角标 </sub>
CTRL + Q 援用 > 援用
CTRL + O 有序列表 1. 有序列表
CTRL + L 链接 [链接](https://imbf.cc)
CTRL + T 表格 `\ 表格 \ ` 放弃开发(无奈实现) x
CTRL + Z 撤回 触发编辑器内内容撤回,与零碎无关
CTRL + SHIFT + S 删除线 ~ 删除线~
CTRL + SHIFT + U 无序列表 - 无序列表
CTRL + SHIFT + C 块级代码 多行代码块
CTRL + SHIFT + I 图片链接 ![图片](https://imbf.cc)
CTRL + SHIFT + Z 前进一步 触发编辑器内内容后退,与零碎无关
CTRL + SHIFT + F 丑化内容
CTRL + ALT + C 行内代码 行内代码块

演示

yarn add md-editor-v3

jsx 语法我的项目

import {defineComponent, reactive} from 'vue';
import Editor from 'md-editor-v3';
import 'md-editor-v3/lib/style.css';
import hljs from 'highlight.js';
import 'highlight.js/styles/atom-one-dark.css';

export default defineComponent({setup() {
    const md = reactive({text: 'default markdown content'});
    return () => (<Editor hljs={hljs} modelValue={md.text} onChange={(value) => (md.text = value)} />
    );
  }
});

vue 模板我的项目

<template>
  <editor v-model="text" pageFullScreen></editor>
</template>

<script>
import {defineComponent} from 'vue';
import Editor from 'md-editor-v3';
import 'md-editor-v3/lib/style.css';

export default defineComponent({
  name: 'VueTemplateDemo',
  components: {Editor},
  data() {
    return {text: '默认值'};
  }
});
</script>

上传图片

默认能够抉择多张图片,反对粘贴板上传图片。

留神:粘贴板上传时,如果是网页上的 gif 图,无奈正确上传为 gif 格局!

async onUploadImg(files: FileList, callback: (urls: string[]) => void) {
  const res = await Promise.all(Array.from(files).map((file) => {return new Promise((rev, rej) => {const form = new FormData();
        form.append('file', file);

        axios
          .post('/api/img/upload', form, {
            headers: {'Content-Type': 'multipart/form-data'}
          })
          .then((res) => rev(res))
          .catch((error) => rej(error));
      });
    })
  );

  callback(res.map((item: any) => item.data.url));
}

结尾

该我的项目目前只生存了 3 周,应用中有 bug 期待你能留言给我,有想要的性能期待理解哦。另外审美个别,轻喷。

正文完
 0