文章目录
- 前言
- 一、安装Vditor
- 二、渲染markdown
- 三、options
- 3.1 自建CDN
- 3.2 outline大纲不显示、不跳转问题
- 3.3 upload 图片/视频上传
- 3.4 toolbar
- 提示位置
- 点击事件
- more中文字
- 3.5 sv分屏渲染模式隐藏编辑框
- 3.6 after中的insertValue或者setValue
前言
Vditor是一款易于使用的 Markdown 编辑器,为适配不同的应用场景而生
笔者只是用了Vditor的编辑模式,对于仅查看的markdown,笔者直接把编辑框给隐藏掉了。
Vditor官网
一、安装Vditor
笔者使用Vue2,vditor使用 3.10.4 版本
npm install vditor --save
二、渲染markdown
<template>
<div id="vditor"></div>
</template>
<script>
import Vditor from "vditor";
// 这里使用官方默认样式
import "vditor/dist/index.css";
export default {
name:'HelloWorld',
mounted(){
let that = this;
let IOptions = {
// cdn:"/vditor",
rtl: false,
cache: {
enable: false,
},
classes: {
preview: "",
},
comment: {
enable: false,
},
counter: {
enable: false,
type: "markdown",
},
customRenders: [],
debugger: false,
fullscreen: {
index: 90,
},
height: "auto",
hint: {
delay: 200,
emoji: {
"+1": "👍",
"-1": "👎",
"confused": "😕",
"eyes": "👀️",
"heart": "❤️",
"rocket": "🚀️",
"smile": "😄",
"tada": "🎉️",
},
// emojiPath: `${Constants.CDN}/dist/images/emoji`,
extend: [],
parse: true,
},
icon: "ant",
lang: "zh_CN",
mode: "ir",
outline: {
enable: false,
position: "left",
},
placeholder: "请输入内容",
preview: {
actions: ["desktop", "tablet", "mobile", "mp-wechat", "zhihu"],
delay: 1000,
// hljs: Constants.HLJS_OPTIONS,
// markdown: Constants.MARKDOWN_OPTIONS,
// math: Constants.MATH_OPTIONS,
maxWidth: 800,
mode: "both",
// theme: Constants.THEME_OPTIONS,
render: {
media: {
enable: true,
}
}
},
link: {
isOpen: true,
},
image: {
isPreview: true,
},
resize: {
enable: false,
position: "bottom",
},
theme: "classic",
toolbar: [
"emoji",
"headings",
"bold",
"italic",
"strike",
"link",
"|",
"list",
"ordered-list",
"check",
"outdent",
"indent",
"|",
"quote",
"line",
"code",
"inline-code",
"insert-before",
"insert-after",
"|",
"upload",
"record",
"table",
"|",
"undo",
"redo",
"|",
"fullscreen",
"edit-mode",
{
name: "more",
toolbar: [
"both",
"code-theme",
"content-theme",
"export",
"outline",
"preview",
"devtools",
"info",
"help",
],
},
],
toolbarConfig: {
hide: false,
pin: false,
},
typewriterMode: true,
undoDelay: 800,
// upload: {
// extraData: {},
// fieldName: "file[]",
// filename: (name: string) => name.replace(/\W/g, ""),
// linkToImgUrl: "",
// max: 10 * 1024 * 1024,
// multiple: true,
// url: "",
// withCredentials: false,
// },
value: "",
width: "auto",
after:()=>{
that.vditor.insertValue("# 插入数据")
//that.vditor.setValue("# 覆盖数据")
}
}
this.vditor = new Vditor("vditor",IOptions)
} ,
data() {
return {
vditor:"",
}
},
created(){
},
methods:{
},
};
</script>
完成后我们可以看到如下页面(如上配置使用的是默认CDN,网络问题会导致很久不出现。内网环境无法加载,需要自建CDN)
三、options
具体含义可以参考-options的部分
3.1 自建CDN
我们如果需要内网运行,或者认为官方网址较慢,可以自建CDN。
自建CDN分为使用下载的npm包中的dist文件和vditor编译源码后的dist文件。
我们下载的包里面可以看到如下内容:
我们需要配置options中的
let IOptions = {
cdn:"http://网址/XXX",
...
}
vditor会在渲染时发送 GET http://网址/XXX/dist 一系列请求。
可以使用如下方式搭建:
- nginx处理
对于nginx的配置需要允许跨域,和将dist配置为alias静态资源
- 后端返回
后端将dist放在资源路径下,接受该Get请求,然后读取本地路径后返回
- 项目文件
直接获取项目本地vditor,这个网上有很多人这么做,但笔者没有成功
3.2 outline大纲不显示、不跳转问题
sv模式(分屏渲染模式)下时是无法渲染大纲的(似乎是因为编辑框没做同步渲染)。我们可以直接覆盖其样式让他展现。
<style scoped>
#vditor :deep(.vditor-outline){
display:block !important;
}
</style>
如果遇到了大纲不跳转问题,可能因为vditor的滚动条不在我们渲染的容器上,比如是一个子节点,这个时候就无法让其滚动。
我们只需要设置高度,让他可以计算自己的长度即可。如:
<div id="vditor" style="height: 800px;"></div>
3.3 upload 图片/视频上传
如果什么都不想改,最简单的方式是让后端返回如下格式的返回值即可:
{
"msg": "",
"code": 0,
"data": {
"errFiles": ['filename', 'filename2'],
"succMap": {
"filename3": "filepath3",
"filename3": "filepath3"
}
}
}
errFiles 是失败的文件名
succMap 是成功的文件map,文件名-请求路径。最后markdown文件使用请求路径去获取图片/视频。
其余参考文档中upload部分,按需写提供的方法接口即可。
如下:
upload: {
extraData: {},
fieldName: "file[]",
filename: (name: string) => name.replace(/\W/g, ""),
linkToImgUrl: "",
max: 10 * 1024 * 1024,
multiple: true,
url: "",
withCredentials: false,
success(editor: HTMLPreElement, msg: string){
...
},
},
3.4 toolbar
提示位置
如图,提示的位置始终向上弹出,如果有header就会很麻烦
我们可以如下配置:
toolbar: [
"emoji",
"headings",
"bold",
"italic",
"strike",
"link",
"|",
{
name:"list",
tipPosition:"s"
},
"ordered-list",
"check",
...
]
如图:
点击事件
同理,如果我们想要覆盖原按钮我们可以进行2.2.3中的操作,如果我们想要实现新的点击事件,我们可以按照官方案例:
toolbar: [
{
hotkey: '⇧⌘S',
name: 'sponsor',
tipPosition: 's',
tip: '成为赞助者',
className: 'right',
icon: '<svg t="1589994565028" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2808" width="32" height="32"><path d="M506.6 423.6m-29.8 0a29.8 29.8 0 1 0 59.6 0 29.8 29.8 0 1 0-59.6 0Z" fill="#0F0F0F" p-id="2809"></path><path d="M717.8 114.5c-83.5 0-158.4 65.4-211.2 122-52.7-56.6-127.7-122-211.2-122-159.5 0-273.9 129.3-273.9 288.9C21.5 562.9 429.3 913 506.6 913s485.1-350.1 485.1-509.7c0.1-159.5-114.4-288.8-273.9-288.8z" fill="#FAFCFB" p-id="2810"></path><path d="M506.6 926c-22 0-61-20.1-116-59.6-51.5-37-109.9-86.4-164.6-139-65.4-63-217.5-220.6-217.5-324 0-81.4 28.6-157.1 80.6-213.1 53.2-57.2 126.4-88.8 206.3-88.8 40 0 81.8 14.1 124.2 41.9 28.1 18.4 56.6 42.8 86.9 74.2 30.3-31.5 58.9-55.8 86.9-74.2 42.5-27.8 84.3-41.9 124.2-41.9 79.9 0 153.2 31.5 206.3 88.8 52 56 80.6 131.7 80.6 213.1 0 103.4-152.1 261-217.5 324-54.6 52.6-113.1 102-164.6 139-54.8 39.5-93.8 59.6-115.8 59.6zM295.4 127.5c-72.6 0-139.1 28.6-187.3 80.4-47.5 51.2-73.7 120.6-73.7 195.4 0 64.8 78.3 178.9 209.6 305.3 53.8 51.8 111.2 100.3 161.7 136.6 56.1 40.4 88.9 54.8 100.9 54.8s44.7-14.4 100.9-54.8c50.5-36.3 108-84.9 161.7-136.6 131.2-126.4 209.6-240.5 209.6-305.3 0-74.9-26.2-144.2-73.7-195.4-48.2-51.9-114.7-80.4-187.3-80.4-61.8 0-127.8 38.5-201.7 117.9-2.5 2.6-5.9 4.1-9.5 4.1s-7.1-1.5-9.5-4.1C423.2 166 357.2 127.5 295.4 127.5z" fill="#141414" p-id="2811"></path><path d="M353.9 415.6m-33.8 0a33.8 33.8 0 1 0 67.6 0 33.8 33.8 0 1 0-67.6 0Z" fill="#0F0F0F" p-id="2812"></path><path d="M659.3 415.6m-33.8 0a33.8 33.8 0 1 0 67.6 0 33.8 33.8 0 1 0-67.6 0Z" fill="#0F0F0F" p-id="2813"></path><path d="M411.6 538.5c0 52.3 42.8 95 95 95 52.3 0 95-42.8 95-95v-31.7h-190v31.7z" fill="#5B5143" p-id="2814"></path><path d="M506.6 646.5c-59.6 0-108-48.5-108-108v-31.7c0-7.2 5.8-13 13-13h190.1c7.2 0 13 5.8 13 13v31.7c0 59.5-48.5 108-108.1 108z m-82-126.7v18.7c0 45.2 36.8 82 82 82s82-36.8 82-82v-18.7h-164z" fill="#141414" p-id="2815"></path><path d="M450.4 578.9a54.7 27.5 0 1 0 109.4 0 54.7 27.5 0 1 0-109.4 0Z" fill="#EA64F9" p-id="2816"></path><path d="M256 502.7a32.1 27.5 0 1 0 64.2 0 32.1 27.5 0 1 0-64.2 0Z" fill="#EFAFF9" p-id="2817"></path><path d="M703.3 502.7a32.1 27.5 0 1 0 64.2 0 32.1 27.5 0 1 0-64.2 0Z" fill="#EFAFF9" p-id="2818"></path></svg>',
click () {alert('捐赠地址:https://ld246.com/sponsor')},
}],
粘贴后如下:
⇧⌘ 打出来比较麻烦,建议直接复制粘贴。
more中文字
如果想不是图标,则直接替换icon即可
{
name: "more",
toolbar: [
"both",
"code-theme",
"content-theme",
"export",
"outline",
"preview",
"devtools",
"info",
"help",
{
hotkey: '⇧⌘S',
name: 'sponsor',
tipPosition: 's',
tip: '成为赞助者',
className: 'right',
icon: '赞助',
click () {alert('捐赠地址:https://ld246.com/sponsor')},
},
],
},
3.5 sv分屏渲染模式隐藏编辑框
通过隐藏编辑框,我们可以直接获取到渲染后的样式,就不用分别调用api去渲染。
我们只需要将 mode设为sv,然后不允许切换编辑模式即可。
<style scoped>
#vditor :deep(.vditor-outline){
display:block !important;
}
#vditor :deep(.vditor-sv){
display:none !important;
}
</style>
3.6 after中的insertValue或者setValue
insertValue 和 setValue 目前是没有回调方法的
当笔者想要读取url中的一些元素来跳转大纲标题时,没办法等待markdown以及大纲渲染完毕后执行跳转到对应标题操作。
因此笔者使用setTimeout定时器来处理,等到获取到子元素后在内部删除该定时器即可。
如果有更好的方式烦请留言。