@banbrider/vue3-vditor
v1.3.0
Published
基于vditor实现的vue3版本的markdown编辑器
Readme
Vue Vditor
一款基于 Vditor 实现的 Vue 版 Markdown 编辑器,支持在 Vue 3.0 中使用。
✨ 特性
- 🎨 三种编辑模式:完整模式、简洁模式、移动端模式
- 🌈 主题切换:支持经典主题和深色主题
- 🛡️ 安全过滤:内置 XSS 过滤机制
- 📝 Markdown 支持:完整的 Markdown 语法支持,兼容 HTML
- 🎯 代码高亮:支持多种代码语言高亮
- 📐 数学公式:支持 KaTeX 和 MathJax 渲染
- 📊 表格支持:完整的表格编辑功能
- 🖼️ 图片上传:支持图片上传和预览
- 📑 目录生成:自动生成文章目录
- 🔄 历史记录:支持撤销/重做操作
- 🔧 高度可配置:丰富的配置选项满足各种需求
- ♿ 无障碍友好:良好的键盘操作支持
- 💚 Vue 2/3 兼容:通过 vue-demi 实现统一 API
🚀 快速开始
安装
Vue 3
npm install vue3-vditor vditor使用方法
方式一:插件注册(推荐)
<template>
<div>
<VueVditor
v-model="content"
:options="options"
@after="handleAfter"
class="editor"
/>
</div>
</template>
<script>
import 'vditor/dist/index.css';
import VueVditor from 'vue3-vditor';
export default {
components: { VueVditor },
data() {
return {
content: '# Hello World\n\n欢迎使用 Vue Vditor',
options: {
height: '500px',
theme: 'classic',
mode: 'wysiwyg'
}
};
},
methods: {
handleAfter(editor) {
console.log('编辑器初始化完成', editor);
}
}
};
</script>
<style>
.editor {
margin: 20px;
}
</style>方式二:直接引入
<template>
<VueVditor v-model="content" class="editor" />
</template>
<script>
import 'vditor/dist/index.css';
import VueVditor from 'vue3-vditor';
export default {
components: { VueVditor },
data() {
return {
content: '# Hello World'
};
}
};
</script>方式三:TypeScript 使用
<template>
<VueVditor
v-model="content"
:options="options"
@after="handleAfter"
class="editor"
/>
</template>
<script lang="ts">
import { ref, defineComponent } from 'vue-demi';
import Vditor from 'vditor';
export default defineComponent({
setup() {
const content = ref('# Hello World');
let editor: Vditor | null = null;
const options = {
height: '500px',
theme: 'classic'
};
const handleAfter = (editorInstance: Vditor) => {
editor = editorInstance;
console.log('编辑器初始化完成');
};
return {
content,
options,
handleAfter
};
}
});
</script>
<style scoped>
.editor {
margin: 20px;
}
</style>📖 配置选项
Props
| 属性 | 类型 | 必填 | 默认值 | 说明 |
|------|------|------|--------|------|
| mode | 'simple' \| 'full' \| 'mobile' | 否 | 'full' | 编辑器模式 |
| modelValue | string | 否 | '' | 编辑器内容(双向绑定) |
| options | IOptions | 否 | {} | Vditor 配置对象 |
Events
| 事件名 | 说明 | 参数 |
|--------|------|------|
| update:modelValue | 内容更新时触发 | value: string |
| after | 编辑器异步渲染完成 | editor: Vditor |
| focus | 编辑器聚焦时触发 | value: string |
| blur | 编辑器失焦时触发 | value: string |
| esc | Esc 按下时触发 | value: string |
| ctrlEnter | ⌘/Ctrl+Enter 按下时触发 | value: string |
| select | 编辑器选中文字时触发 | value: string |
Methods
通过 @after 事件获取 Vditor 实例后,可调用 Vditor 所有方法:
<VueVditor
v-model="content"
@after="handleAfter"
/>let editor = null;
function handleAfter(editorInstance) {
editor = editorInstance;
// 插入内容
editor.insertValue('');
// 获取 Markdown 内容
const markdown = editor.getValue();
// 获取 HTML 内容
const html = editor.getHTML();
// 启用编辑器
editor.enable();
// 禁用编辑器
editor.disabled();
// 销毁编辑器
editor.destroy();
// 切换主题
editor.setTheme('dark', 'dark');
}🎯 编辑器模式
完整模式 (full)
包含所有工具栏选项,功能最全面。
<VueVditor v-model="content" mode="full" />简洁模式 (simple)
精简工具栏,适合轻量级场景。
<VueVditor v-model="content" mode="simple" />移动端模式 (mobile)
为移动设备优化,提供基本编辑功能。
<VueVditor v-model="content" mode="mobile" />🎨 高级配置
基础配置
const options = {
// 编辑器高度
height: 500,
// 编辑器最小高度
minHeight: 200,
// 编辑器宽度
width: '100%',
// 占位符文本
placeholder: '请输入内容...',
// 编辑模式:wysiwyg(所见即所得)、sv(分屏)、ir(即时渲染)
mode: 'wysiwyg',
// 主题:classic(经典)、dark(深色)
theme: 'classic',
// 图标风格:ant、material
icon: 'ant',
// 多语言:zh_CN、en_US、ja_JP、ko_KR、ru_RU、zh_TW
lang: 'zh_CN',
// 是否启用打字机模式
typewriterMode: false,
// 是否启用全屏
fullscreen: true,
// 输入为空时的提示
placeholder: '开始输入...'
};上传配置
const options = {
upload: {
// 上传 URL(需要后端支持)
url: '/api/upload',
// 上传文件最大大小(字节)
max: 1024 * 1024 * 10, // 10MB
// 文件上传类型
accept: 'image/*',
// 是否允许多文件上传
multiple: true,
// 文件字段名
fieldName: 'file',
// 自定义上传处理器
handler(files) {
// files: File[]
// 返回 'uploading' 表示正在上传
return 'uploading';
// 返回 'error' 表示上传失败
return 'error';
// 返回 URL 字符串表示上传成功
return 'https://example.com/image.jpg';
},
// 上传成功回调
success(editor, msg) {
console.log('上传成功:', msg);
},
// 上传失败回调
error(msg) {
console.error('上传失败:', msg);
},
// 对服务端返回的数据进行转换
format(files, responseText) {
// 解析响应并返回图片 URL
return JSON.parse(responseText).url;
},
// 链接转图片上传的格式化
linkToImgFormat(responseText) {
return JSON.parse(responseText).url;
}
}
};预览配置
const options = {
preview: {
// 预览延迟时间(毫秒)
delay: 1000,
// 预览区域最大宽度
maxWidth: 768,
// 显示模式:both(分屏)、editor(仅编辑器)
mode: 'both',
// 代码高亮配置
hljs: {
enable: true,
lineNumber: false,
style: 'github' // 可选: github、atom-one-dark、mono-blue 等
},
// 数学公式配置
math: {
engine: 'KaTeX', // 可选: KaTeX、MathJax
inlineDigit: false,
macros: {}
},
// Markdown 解析配置
markdown: {
autoSpace: false,
paragraphBeginningSpace: false,
fixTermTypo: false,
toc: false,
footnotes: true,
codeBlockPreview: true,
mathBlockPreview: true,
sanitize: true,
linkBase: '',
linkPrefix: '',
listStyle: false,
mark: true
},
// 预览主题
theme: {
current: 'classic',
list: {
classic: 'https://cdn.jsdelivr.net/npm/[email protected]/dist/css/content-theme/default.css',
light: 'https://cdn.jsdelivr.net/npm/[email protected]/dist/css/content-theme/default.css',
dark: 'https://cdn.jsdelivr.net/npm/[email protected]/dist/css/content-theme/github-dark.css'
}
},
// 预览设备预设
actions: ['desktop', 'tablet', 'mobile']
}
};工具栏配置
const options = {
// 完整工具栏配置
toolbar: [
'emoji',
'headings',
'bold',
'italic',
'strike',
'|',
'list',
'ordered-list',
'check',
'outdent',
'indent',
'|',
'quote',
'line',
'code',
'inline-code',
'insert-before',
'insert-after',
'|',
'table',
'|',
'undo',
'redo',
'|',
'fullscreen',
'edit-mode',
'outline',
'preview',
'devtools',
'help'
]
};
// 简洁模式工具栏
const simpleConfig = [
'emoji',
'headings',
'bold',
'italic',
'strike',
'|',
'list',
'ordered-list',
'check',
'outdent',
'indent',
'|',
'quote',
'line',
'code',
'inline-code',
'insert-before',
'insert-after',
'|',
'table'
];
// 移动端模式工具栏
const mobileConfig = [
'emoji',
'link',
'upload',
'edit-mode',
{
name: 'more',
toolbar: ['insert-after', 'fullscreen', 'preview']
}
];目录配置
const options = {
outline: {
enable: true,
position: 'left' // 可选: left、right
}
};计数器配置
const options = {
counter: {
enable: true,
max: 10000,
type: 'markdown' // 可选: markdown、text
}
};历史记录配置
const options = {
undoDelay: 5000 // 历史记录间隔(毫秒)
};快捷键配置
const options = {
tab: '\t' // Tab 键操作字符串
};🎯 常见用法
基础编辑器
<VueVditor v-model="content" height="500px" />深色主题
<VueVditor v-model="content" :options="{ theme: 'dark' }" />禁用编辑器
<VueVditor
v-model="content"
:disabled="true"
@after="handleAfter"
/>获取内容并保存
const saveContent = () => {
if (editor) {
const markdown = editor.getValue();
// 发送到服务器
api.save(markdown);
}
};监听内容变化
const handleInput = (value) => {
console.log('内容变化:', value);
};主题切换
const toggleTheme = () => {
if (editor) {
const currentTheme = editor.vditor.options.theme;
const newTheme = currentTheme === 'dark' ? 'classic' : 'dark';
editor.setTheme(newTheme);
}
};插入指定内容
const insertAtCursor = () => {
if (editor) {
editor.insertValue('```javascript\nconsole.log("Hello");\n```');
}
};获取选中内容
const getSelection = () => {
if (editor) {
const selection = editor.getSelection();
console.log('选中内容:', selection);
}
};🔧 本地开发
# 克隆项目
git clone https://gitee.com/banyunjian/vue3-vditor.git
cd vue3-vditor
# 安装依赖
npm install
# 启动开发服务器
npm run dev
# 构建库
npm run build
# 预览构建结果
npm run serve开发服务器地址
启动后访问:http://localhost:3000
📦 构建
# 构建生产版本
npm run build
# 构建并发布(使用 standard-version)
npm run release构建产物位于 lib/ 目录:
index.umd.js- UMD 格式(支持浏览器全局变量)index.mjs- ES Module 格式
🤝 贡献指南
欢迎贡献代码!请遵循以下步骤:
- Fork 本仓库
- 创建特性分支 (
git checkout -b feature/AmazingFeature) - 提交更改 (
git commit -m 'Add some AmazingFeature') - 推送到分支 (
git push origin feature/AmazingFeature) - 开启 Pull Request
提交规范
本项目使用 Conventional Commits 规范:
feat:新功能fix:修复 bugdocs:文档更新style:代码格式调整refactor:代码重构perf:性能优化test:测试相关chore:构建/工具相关
📄 License
MIT License
🙏 致谢
- Vditor - 强大的 Markdown 编辑器
- vue-vditor - Vue 2/3兼容的 vditor组件
- Vue - 渐进式 JavaScript 框架
- vue-demi - Vue 2/3 兼容层
