vditor
安装
pnpm i vditor
二次封装
针对vditor进行封装,扩展了mermaid相关的示例,不影响直接使用vditor
二次封装代码位置
import { useVditor } from '/@/views/demo/hooks/web/useVditor';
功能:
效果:
使用说明
vditor官方给的文档非常详细,也有中文说明,目前做了部分测试,未发现阻断性问题,后边会列出测试过程中遇到的一些问题以及注意事项
测试代码
vue
<template>
<div id="vditor"></div>
<button @click="test">2222</button>
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue';
import Vditor from 'vditor';
import 'vditor/dist/index.css';
import { useVditor } from '/@/views/demo/hooks/web/useVditor';
const vditorss = ref<Vditor | null>(null);
function test() {
// console.log(vditor.value.vditor.options.toolbar)
vditorss.value!.setValue(
'Vue Composition API + Vditor + TypeScript Minimal Example 11111',
);
}
interface MyResponse {
code: number;
message: string;
result: any;
}
interface NeedResult {
code: number;
msg: string;
data: any;
}
onMounted(() => {
const { vditor } = useVditor('vditor', {
// cdn: 'https://cdn.jsdelivr.net/npm/vditor@3.8.12',
cdn: '/resource',
height: 600,
toolbarConfig: {
pin: true, // 页面吸顶效果,类似于菜单始终处于顶部
hide: false, // 是否隐藏工具栏
},
preview: {
// 预览状态下 的操作按钮["desktop", "tablet", "mobile", "mp-wechat", "zhihu"],
// 可以拷贝针对不同平台格式的文档
actions: [],
},
cache: {
enable: false,
},
toolbar: [
'mermaid', // 自定义 使用useVditor可以使用
// 'emoji',
// 'headings',
// 'bold',
// 'italic',
// 'strike',
// '|',
// 'line',
// 'quote',
// 'list',
// 'ordered-list',
// 'check',
// 'outdent',
// 'indent',
// 'code',
// 'inline-code',
// 'insert-after',
// 'insert-before',
// 'undo',
// 'redo',
// 'upload',
// 'link',
// 'table',
// 'record',
'edit-mode',
// 'both',
'preview',
// 'fullscreen',
// 'outline',
// 'code-theme',
// 'content-theme',
// 'export',
// 'devtools',
// 'info',
// 'help',
// 'br',
],
after: () => {
// vditor.value is a instance of Vditor now and thus can be safely used here
vditor.value!.setValue(
'Vue Composition API + Vditor + TypeScript Minimal Example',
);
},
upload: {
// accept: 'image/*,.mp3, .wav, .rar', //上传文件类型
// token: 'xxxx',
// filename: function (name) {
// console.log('filename:' + name);
// return name
// .replace(/[^(a-zA-Z0-9\u4e00-\u9fa5\.)]/g, '')
// .replace(/[\?\\/:|<>\*\[\]\(\)\$%\{\}@~]/g, '')
// .replace('/\\s/g', '');
// }, // 替换文件名称
// fieldName: 'files', // 上传字段名称
url: '/api/markdown-upload', // 本地文件上传地址,后续会给出后端接口写法
format(files: File[], responseText: string): string {
// 对返回体进行处理, 返回值为 string
// files文件信息
// responseText返回体字符串
// 需求结构体
/**
* {
* "msg": "",
* "code": 0,
* "data": {
* "errFiles": ['filename', 'filename2'],
* "succMap": {
* "filename3": "filepath3",
* "filename3": "filepath3"
* }
* }
* }
*/
console.log(files, responseText);
let result: NeedResult = {} as NeedResult;
const response: MyResponse = JSON.parse(responseText);
result.code = 0; // 注意、注意、注意,结构体要求此处为0
result.msg = response.message;
result.data = response.result;
/**
* 后端返回值,需要处理成固定结构
* {
* "success":true,
* "message":"OK",
* "result":{
* "succMap":{
* "image.png":"/midway-upload-files/upload_1667184793903.0.3117785344185593.0.png"
* }
* }
* }
*/
return JSON.stringify(result);
},
linkToImgUrl: '/api/url', // 从互联网复制文章,存在外网图片,上传到后端的接口,后续会给出后端接口写法
linkToImgFormat(responseText: string): string {
let result: NeedResult = {} as NeedResult;
const response: MyResponse = JSON.parse(responseText);
result.code = 0; // 注意、注意、注意,结构体要求此处为0,否则替换失败
result.msg = response.message;
result.data = response.result;
console.log(result);
return JSON.stringify(result);
},
linkToImgCallback(responseText: string) {
console.log(responseText);
},
},
});
vditorss.value = vditor.value;
});
</script>
<style></style>
图片上传后端参考
本地文件上传接口(如复制粘贴图片到编辑器中)
参数file是一个文件对象
互联网文章图片上传
参数中的url为互联网图片地址,需要服务器端进行图片下载
注意事项
1、关于CDN的问题
遇到的问题:
由于官方使用的CDN不太容易访问,出现引用了vditor,但是界面却没有显示编辑器
解决方案:
- 按照官方示例搭建CDN(未测试)
- 将vditor源码打包后将dist包放到public目录下进行引入(本次测试使用的该方式)
2、关于vite与vditor兼容的问题
遇到的问题:
出现
Lute is not define
错误解决方案:
- vite.config.ts文件中有process.xx相关的配置
- vite.config.ts文件中有process.xx相关的配置
3、复制互联网文章内图片上传服务器遇到的问题,相关功能 upload.linkToImgFormat
遇到的问题:
upload.linkToImgFormat
按返回值结构处理后,连接未替换成站内url注意事项:
js
// POST data
xhr.send(JSON.stringify({url: src})); // src 为站外图片地址
// return data
{
msg: '',
code: 0, // 注意-注意-注意,此处必须为 0
data : {
originalURL: '', // 原url
url: '' // 站内url
}
}