协作安装指南
本指南将指导您在 Tiptap 编辑器中启用协作编辑。如果您已经在使用 Tiptap 编辑器,可以直接跳到“添加协作”部分。
安装 Tiptap 编辑器
如果没有安装 Tiptap 编辑器,请使用以下命令在您的 CLI 中为 React 或 Vue 项目安装基本编辑器和示例所需的扩展:
npm install @tiptap/extension-document @tiptap/extension-paragraph @tiptap/extension-text @tiptap/react
安装完成后,您可以使用这个基础设置启动 Tiptap 编辑器。只需在项目中添加以下代码片段: https://embed.tiptap.dev/preview/Examples/Minimal
添加协作
要在您的 Tiptap 编辑器中引入团队协作功能,需要将 Yjs 库和协作扩展集成到前端。此设置使用共享文档模型 Y.Doc,而不仅仅是处理纯文本。
接下来,我们将连接 Y.Doc 到 TiptapCollabProvider,以同步用户交互。
集成 Yjs 和协作扩展
将协作扩展和 Yjs 库添加到您的前端:
npm install @tiptap/extension-collaboration yjs
然后,在 index.jsx
文件中添加这些新的导入:
import './styles.scss'
import Document from '@tiptap/extension-document'
import Paragraph from '@tiptap/extension-paragraph'
import Text from '@tiptap/extension-text'
import { EditorContent, useEditor } from '@tiptap/react'
import React from 'react'
import Collaboration from '@tiptap/extension-collaboration'
import * as Y from 'yjs'
export default () => {
const doc = new Y.Doc() // 初始化 Y.Doc 用于共享编辑
const editor = useEditor({
extensions: [
Document,
Paragraph,
Text,
Collaboration.configure({
document: doc // 将 Y.Doc 配置为协作
})
],
content: `
<p>
这是 Tiptap 的极简版本。它支持文档,包含段落和文本。仅此而已。对于真正的极简主义者来说可能有点多了。
</p>
<p>
段落扩展实际上并不必要,但至少需要一个节点。当然,这个节点可以是不同的东西。
</p>
`,
})
return (
<EditorContent editor={editor} />
)
}
现在,您的编辑器已经准备好进行协作编辑!
连接至协作服务器
为了实现协作功能,请安装 @hocuspocus/provider
包:
npm install @hocuspocus/provider
接下来,在 index.jsx
文件中根据您的服务器详细信息配置 Hocuspocus 提供者:
- name:用作同步标识符的文档名称。
- appID:在您的 云端账户中启动应用后,将在云界面中找到。对于本地部署,请将
appID
替换为baseUrl
。 - token:测试时使用云端接口的 JWT,但生产环境请生成自己的 JWT。
添加以下代码以完成设置:
import './styles.scss'
import Document from '@tiptap/extension-document'
import Paragraph from '@tiptap/extension-paragraph'
import Text from '@tiptap/extension-text'
import { EditorContent, useEditor } from '@tiptap/react'
import React from 'react'
import Collaboration from '@tiptap/extension-collaboration'
import * as Y from 'yjs'
// 导入提供者和 useEffect
import {useEffect} from 'react'
import { TiptapCollabProvider } from '@hocuspocus/provider'
export default () => {
const doc = new Y.Doc()
const editor = useEditor({
extensions: [
Document,
Paragraph,
Text,
Collaboration.configure({
document: doc,
}),
],
content: `
<p>
这是 Tiptap 的极简版本。它支持文档,包含段落和文本。仅此而已。对于真正的极简主义者来说可能有点多了。
</p>
<p>
段落扩展实际上并不必要,但至少需要一个节点。当然,这个节点可以是不同的东西。
</p>
`,
})
// 连接到您的协作服务器
useEffect(() => {
const provider = new TiptapCollabProvider({
name: "document.name", // 文档名称用于同步。这是您的文档名。
appId: '7j9y6m10', // 云端仪表板 AppID 或 `baseURL`(本地部署)
token: 'notoken', // 测试时使用的 JWT 或生产环境自定义的 JWT
document: doc,
// onSynced 回调确保只在初次加载时设置初始内容,防止每次编辑器同步时重复加载内容。
onSynced() {
if( !doc.getMap('config').get('initialContentLoaded') && editor ){
doc.getMap('config').set('initialContentLoaded', true);
editor.commands.setContent(`
<p>
这是 Tiptap 的极简版本。它支持文档,包含段落和文本。仅此而已。对于真正的极简主义者来说可能有点多了。
</p>
<p>
段落扩展实际上并不必要,但至少需要一个节点。当然,这个节点可以是不同的东西。
</p>
`)
}
}
})
})
return (
<EditorContent editor={editor} />
)
}
遵循这些步骤后,您应该能够在两个不同的浏览器中通过单独的 WebSocket 连接同时连接到同一文档。
为了清楚地测试协作功能,建议使用两个不同的浏览器,以确保唯一的 WebSocket 连接。
正确初始化内容
在 Tiptap 编辑器中启用协作后,可能会发现每次编辑器加载时初始内容都会重复添加。为了防止这种情况,使用 .setContent()
方法仅设置一次初始内容。
import './styles.scss'
import Document from '@tiptap/extension-document'
import Paragraph from '@tiptap/extension-paragraph'
import Text from '@tiptap/extension-text'
import { EditorContent, useEditor } from '@tiptap/react'
import React from 'react'
import * as Y from 'yjs'
import Collaboration from '@tiptap/extension-collaboration'
import {useEffect} from 'react'
import { TiptapCollabProvider } from '@hocuspocus/provider'
export default () => {
const doc = new Y.Doc()
const editor = useEditor({
extensions: [
Document,
Paragraph,
Text,
Collaboration.configure({
document: doc
})
],
// 移除编辑器初始化时自动添加内容的代码。
})
useEffect(() => {
const provider = new TiptapCollabProvider({
name: "document.name", // 文档名称用于同步。这是您的文档名。
appId: '7j9y6m10', // 云端仪表板 AppID 或 `baseURL`(本地部署)
token: 'notoken', // 测试时使用的 JWT 或生产环境自定义的 JWT
document: doc,
// onSynced 回调确保只在初次加载时设置初始内容。
onSynced() {
if( !doc.getMap('config').get('initialContentLoaded') && editor ){
doc.getMap('config').set('initialContentLoaded', true);
// 使用 editor.setContent() 设置初始内容,避免每次编辑器同步时重复加载。
editor.commands.setContent(`
<p>
这是 Tiptap 的极简版本。它支持文档,包含段落和文本。仅此而已。对于真正的极简主义者来说可能有点多了。
</p>
<p>
段落扩展实际上并不必要,但至少需要一个节点。当然,这个节点可以是不同的东西。
</p>
`)
}
}
})
})
return (
<EditorContent editor={editor} />
)
}
这将确保只设置一次初始内容。要测试不同的初始内容,请更改 name
参数(例如,从 document.name
更改为 document.name2
)创建新的文档。
禁用默认撤销/重做功能
如果将协作集成到本示例之外的编辑器中,您可能需要禁用编辑器的默认历史功能。这是必要的,以避免与协作历史管理冲突:您不希望撤销或重做其他人的更改。
此操作仅在您的项目中包含 Tiptap StarterKit 或 History 扩展时才需要。
const editor = useEditor({
extensions: [
StarterKit.configure({
history: false, // 禁用默认历史,使用协作的管理历史功能
}),
...
遵循本指南,您将设置一个基本但功能齐全的协作 Tiptap 编辑器,通过