1. 特性:
- 是一个前端编辑器库
- 基于ProseMirror(一个更轻量的编辑器库,tiptap是对它的拓展)开发
- 无头:非开箱即用的,只提供各种功能。样式和交互自由度高
- 框架无关:只要基于web前端,无论是纯js,react/vue...都可以使用
- 扩展性:提供了自定义扩展能力,满足各种个性化需求
2. 安装使用
2.1 基础概念
首先要了解tiptap的项目构成:
@tiptap/pm对ProseMirror核心模块的封装,如:
state 状态 | view 视图 | model 模型 | commands 指令 | schema 框架@tiptap/core核心库,概念:Editor编辑器核心模块Extensions扩展模块Schema文档结果定义,即哪些节点(Node)和标记(Mark)是允许出现的Transaction代表一次变化,基于此实现对文档的交互操作和回退
@tiptap/starter-kit包含了基础组件模块:- Node:段落:Paragraph | 标题:Heading | 代码块:CodeBlock | 引用块:Blockquote | 无序列表:BulletList | 有序列表:OrderedList | 列表项:ListItem | 分割线:HorizontalRule | 图片:Image
- Mark:加粗:Bold | 斜体:Italic | 删除线:Strike | 行内代码:Code | 强制换行:HardBreak | 链接:Link
- 其他:撤销和重做:History | 文档根节点:Document
2.2 使用(纯JS环境)
以下是一个最基础的Tiptap使用案例(重点关注🌈):
import { Editor } from '@tiptap/core' // 1.引入核心Editor模块
import StarterKit from '@tiptap/starter-kit' // 2. 引入基础组件模块
new Editor({ // 4. 🌈创建tiptap Editor实例
element: document.querySelector('.element'), // 5. element:实例参数,选取挂载节点
extensions: [StarterKit], // 6. 🌈extensitions:加入扩展
content: '<p>Hello World!</p>', // 7. 🌈content:插入内容
})
2.2.1 Editor配置项
Editor类还有哪些配置参数呢(重点关注🌈):
import { Editor } from '@tiptap/core' // 1. 引入核心库
// 这里只是为了告诉你可以引入多个扩展,一般用@tiptap/starter-kit就行了
import Document from '@tiptap/extension-document' // 3. 引入根节点
import Paragraph from '@tiptap/extension-paragraph' // 4. 同上,引入段落
import Text from '@tiptap/extension-text' // 5. 同上,引入文本
new Editor({ // 7. 开始,创建实例
element: document.querySelector('.element'), // 8. 选定挂载节点
extensions: [Document, Paragraph, Text], // 9. 加入扩展
content: '<p>Example Text</p>', // 10. 插入内容
autofocus: true, // 11. 🌈是否自动焦点:'start' | 'end' | 'all' | number | boolean | null
editable: true, // 12. 🌈是否可编辑:boolean
injectCSS: false, // 13. 🌈禁用默认样式
})
2.2.2 配置扩展组件
另外,我们可以对extensions的传入项(Extensions: Node | Mark | Extension)进行自由配置。
比如Heading的levels指定标题有什么等级(type Level = 1 | 2 | 3 | 4 | 5 | 6)
默认值是:[1, 2, 3, 4, 5, 6],如果只想要h1 h2 h3(重点关注🌈):
import { Editor } from '@tiptap/core' // 1. 引入核心库
// ... 2. 引入其他组件
import Heading from '@tiptap/extension-heading' // 3. 引入Heading
new Editor({
element: document.querySelector('.element'),
extensions: [
// ... 8. 加入其他组件
Heading.configure({ // 9. 🌈修改默认参数。所有的Node|Mark|Extension都有config和configure
levels: [1, 2, 3], // 10. 🌈levels:设置heading允许的level
HTMLAttributes: { // 11. 🌈HTMLAttributes:设置组件HTML标签的属性
class: 'custom-heading' // 12. 🌈自定义类名
},
}),
],
})
也可以修改编辑器根节点的属性,顺便看看tiptap Editop的配置结构(重点关注🌈):
new Editor({ // 1. EditorOptions:针对整个Editor对象的配置,用于创建Editor对象
editorProps: { // 2. EditorProps:核心配置,用于精细管理editor行为
attributes: { // 3. EditorProps.attributes 根节点标签属性
class: 'my-editor', // 4. 🌈设置类名
},
// 6. 🌈此外,EditorProps 还包含:
// 7. 基础事件
// handleKeyDown: ... // 8. 键盘事件
// handleClick: ... // 9. 鼠标事件
// handleDrop: ... // 10. 拖拽事件
// 11. 高级事件
// handleScrollToSelection: ... // 12. 当视图在更新其状态之后试图将所选内容滚动到视图中时
// createSelectionBetween: ... // 13. 文本选取发生改变事触发
// ...
},
// 16. 🌈EditorOptions的属性还包括:
// 17. 必要属性
element: document.querySelector('.element'), // 18. Element:挂载元素对象
extensions: [Document, Paragraph, Text], // 19. Extensions:拓展组件、节点
content: '<p>Example Text</p>', // 20. Content:内容
// 21. 配置项(常用例举)
editable: true, // 22. 是否允许编辑
autofocus: true, // 23. 自动获取焦点行为
// 24. 顶层事件(常用例举)
// onCreate: ... // 25. 创建事件
// onUpdate: ... // 26. 内容更新事件
// onFocus: ... // 27. 焦点获取事件
})
总的来说,Tiptap采用的是一个选项式optionality的使用思路,
我们要重点关注这棵"选项树"的关键节点和定义:
mindmap
Editor编辑器核心
EditorOptions顶层
element:Element 挂载元素
content:Content 内容
extensions:Extension | Node | Mark 拓展类型
...
editorProps:EditorProps 核心
handleKeyDown
handleClick
handleDrop
handleScrollToSelection
createSelectionBetween
...
后面的学习就是这棵基础但不完整的树的细节刻画了。
敬请期待。