开发背景

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

阐明

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

代码仓库:md-editor-v3

性能一览

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

预览图

默认模式下:

暗黑模式下:

在线预览

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

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

apis

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

props

名称类型默认值阐明
modelValueString''md 编辑内容,vue 模板反对双向绑定(v-model="value")
editorClassString''编辑器最外层款式
hljsObjectnull我的项目中应用到了 highlight,可将实例间接传递,生产环境则不会申请 CDN,须要手动导入反对的高亮代码款式
highlightJsStringhighlight.jshighlightJs CDN
highlightCssStringatom-one-dark预览高亮代码款式
historyLengthNumber10最大记录操作数(太大会占用内存)
pageFullScreenBooleanfalse浏览器内全屏
previewBooleantrue预览模式
htmlPreviewBooleanfalsehtml 预览
languageString'zh-CN'内置中英文('zh-CN','en-US'),可自行扩大其余语言,同时可笼罩内置的中英文
languageUserDefinedArray[{key: StaticTextDefaultValue}]通过这里扩大语言,批改 language 值为扩大 key 即可,类型申明可手动导入
toolbarsArray[all]选择性展现工具栏,可选内容如下[toolbars]
prettierBooleantrue是否启用 prettier 优化 md 内容
prettierCDNStringstandalone
prettierMDCDNStringparser-markdown
editorNameString'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;  };}

事件绑定

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

快捷键

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

键位性能阐明开发标记
CTRL + S保留触发编辑器的onSave回调
CTRL + B加粗**加粗**
CTRL + U下划线<u>下划线</u>
CTRL + I斜体*斜体*
CTRL + 1-61-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期待你能留言给我,有想要的性能期待理解哦。另外审美个别,轻喷。