导航
Tiptap 是一个基于 ProseMirror 的富文本编辑器框架,设计目标是灵活性和可扩展性。Tiptap 让开发者可以轻松构建功能强大的富文本编辑器,同时支持自定义节点(Node)、标记(Mark)和插件(Plugin)的扩展。
使用 npm 或 yarn 安装 Tiptap 和核心依赖:
# Vue 3 环境下
npm install @tiptap/core @tiptap/vue-3 @tiptap/starter-kit
文件结构
src/
├── components/
│ └── Editor.vue
└── main.js
Editor.vue
<template>
<div>
<editor-content :editor="editor" />
</div>
</template>
<script>
import { ref, onMounted, onBeforeUnmount } from 'vue';
import { EditorContent, useEditor } from '@tiptap/vue-3';
import StarterKit from '@tiptap/starter-kit';
export default {
name: 'Editor',
components: {
EditorContent,
},
setup() {
const editor = useEditor({
extensions: [StarterKit],
content: `
<h2>Welcome to Tiptap</h2>
<p>This is a basic example.</p>
`,
});
onMounted(() => {
console.log('Editor mounted.');
});
onBeforeUnmount(() => {
if (editor) editor.destroy();
});
return { editor };
},
};
</script>
<style>
/* 添加你自己的样式 */
</style>
import { createApp } from 'vue';
import App from './App.vue';
createApp(App).mount('#app');
Tiptap 提供了扩展功能,以下是一些常见扩展的示例。
安装图片扩展:
npm install @tiptap/extension-image
在编辑器中添加 Image 扩展:
import Image from '@tiptap/extension-image';
const editor = useEditor({
extensions: [StarterKit, Image],
content: `
<p>Click the button to add an image:</p>
`,
});
// 插入图片
editor.chain().focus().setImage({ src: '<https://via.placeholder.com/150>' }).run();
安装表格扩展:
npm install @tiptap/extension-table @tiptap/extension-table-row @tiptap/extension-table-cell @tiptap/extension-table-header
在编辑器中添加表格扩展:
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';
const editor = useEditor({
extensions: [StarterKit, Table, TableRow, TableCell, TableHeader],
});
// 插入 3x3 表格
editor.chain().focus().insertTable({ rows: 3, cols: 3 }).run();
Tiptap 提供强大的扩展机制,你可以通过定义自定义 Node 来实现自定义行为。
创建一个简单的 Custom Node
import { Node } from '@tiptap/core';
export const CustomNode = Node.create({
name: 'customNode',
group: 'block',
content: 'text*',
parseHTML() {
return [{ tag: 'div[data-type="custom"]' }];
},
renderHTML({ HTMLAttributes }) {
return ['div', { 'data-type': 'custom', ...HTMLAttributes }, 0];
},
addCommands() {
return {
setCustomNode: () => ({ commands }) => {
return commands.insertContent('<div data-type="custom">Custom Node</div>');
},
};
},
});
在编辑器中注册自定义节点:
import { CustomNode } from './CustomNode';
const editor = useEditor({
extensions: [StarterKit, CustomNode],
});
// 插入自定义节点
editor.chain().focus().setCustomNode().run();