Tiptap 是一款基于 ProseMirror 构建的现代化富文本编辑器,以其高度可定制性和插件化架构在 Vue/React 生态中备受青睐。本文将系统介绍如何在 Vue 3 项目中集成 Tiptap,并实现基础功能与进阶扩展。
一、环境准备与基础集成
1. 安装依赖
npm install @tiptap/vue-3 @tiptap/starter-kit
@tiptap/vue-3:Vue 3 专用适配器@tiptap/starter-kit:基础功能包(含标题、列表、撤销等)
2. 创建编辑器组件
<template>
<div class="editor-container">
<editor-content :editor="editor" class="editor" />
</div>
</template>
<script setup>
import { onBeforeUnmount, ref } from 'vue'
import { Editor, EditorContent } from '@tiptap/vue-3'
import StarterKit from '@tiptap/starter-kit'
const editor = ref(null)
onMounted(() => {
editor.value = new Editor({
extensions: [StarterKit],
content: '<p>欢迎使用 Tiptap 编辑器</p>',
})
})
onBeforeUnmount(() => {
editor.value?.destroy()
})
</script>
<style scoped>
.editor {
border: 1px solid #ddd;
padding: 16px;
min-height: 300px;
border-radius: 4px;
}
</style>
二、核心功能扩展
1. 常用扩展插件
| 插件名称 | 安装命令 | 功能说明 |
|---|---|---|
@tiptap/extension-link |
npm install @tiptap/extension-link |
链接插入与编辑 |
@tiptap/extension-image |
npm install @tiptap/extension-image |
图片上传(需自定义上传逻辑) |
@tiptap/extension-table |
npm install @tiptap/extension-table |
表格操作(含行列增删) |
@tiptap/extension-code-block-lowlight |
npm install @tiptap/extension-code-block-lowlight lowlight |
代码高亮(需配合语法库) |
2. 完整扩展配置示例
import Link from '@tiptap/extension-link'
import Image from '@tiptap/extension-image'
import Table from '@tiptap/extension-table'
import TableRow from '@tiptap/extension-table-row'
import TableCell from '@tiptap/extension-table-cell'
import TableHeader from '@tiptap/extension-table-header'
import CodeBlockLowlight from '@tiptap/extension-code-block-lowlight'
import { lowlight } from 'lowlight/lib/common'
const editor = new Editor({
extensions: [
StarterKit,
Link.configure({
openOnClick: false, // 禁用点击跳转
validate: href => /^https?:\/\//.test(href), // 验证URL格式
}),
Image.configure({
allowBase64: true, // 允许base64图片
HTMLAttributes: {
class: 'editor-image',
},
}),
Table.configure({
resizable: true,
}),
TableRow,
TableCell,
TableHeader,
CodeBlockLowlight.configure({
lowlight,
}),
],
content: '<p>开始编辑...</p>',
})
三、进阶功能实现
1. 自定义上传图片
import { uploadImage } from '@/api/upload' // 假设存在上传接口
const editor = new Editor({
extensions: [
Image.configure({
inline: true, // 行内图片
async onUpload({ file }) {
const formData = new FormData()
formData.append('file', file)
const { data } = await uploadImage(formData)
return data.url // 返回图片URL
},
}),
],
})
2. 实时字数统计
<template>
<div>
<editor-content :editor="editor" />
<div class="word-count">当前字数:{{ characterCount }}</div>
</div>
</template>
<script setup>
import { computed } from 'vue'
import CharacterCount from '@tiptap/extension-character-count'
const editor = new Editor({
extensions: [
StarterKit,
CharacterCount.configure({
limit: 1000, // 限制1000字
}),
],
})
const characterCount = computed(() => editor.storage.characterCount.characters())
</script>
3. 自定义工具栏
<template>
<div class="toolbar">
<button @click="editor.chain().focus().toggleBold().run()" :disabled="!editor.can().chain().focus().toggleBold().run()">
<strong>B</strong>
</button>
<button @click="editor.chain().focus().toggleItalic().run()" :disabled="!editor.can().chain().focus().toggleItalic().run()">
<em>I</em>
</button>
<!-- 更多按钮... -->
</div>
<editor-content :editor="editor" />
</template>
四、性能优化与最佳实践
- 资源清理 :在组件卸载时调用
editor.destroy() - 懒加载:对非首屏编辑器使用动态导入
- 插件管理:按需加载插件,避免过度扩展
- 内容安全:对用户输入进行XSS过滤(Tiptap默认已转义)
五、常见问题解决
-
Vue 3组合式API适配
使用
ref包裹编辑器实例,并通过onMounted/onBeforeUnmount管理生命周期 -
TypeScript支持
安装类型定义包:
npm install --save-dev @tiptap/pm @tiptap/vue-3并在
tsconfig.json中添加:{ "compilerOptions": { "types": ["@tiptap/pm"] } } -
SSR兼容性
在服务端渲染时需跳过编辑器初始化,通过
isClient判断:import { isClient } from '@vueuse/core' if (isClient) { editor = new Editor({ /* ... */ }) }六、插件生态推荐
插件名称 功能说明 官方文档 @tiptap/extension-history撤销/重做历史记录 History Extension @tiptap/extension-markdownMarkdown语法支持 Markdown Extension tiptap-extension-global-drag-handle全局拖拽把手(需单独安装) Global Drag Handle
总结
Tiptap 通过其模块化设计,允许开发者从基础功能开始逐步构建复杂编辑器。在实际项目中,建议:
- 按需引入插件,避免过度扩展
- 封装自定义工具栏组件,提升可维护性
- 对用户输入内容进行二次校验,确保数据安全
通过本文的实践指南,开发者可以快速掌握 Tiptap 的核心用法,并根据业务需求进行深度定制。