深入浅出 TinyEditor 富文本编辑器系列4:基础使用示例
你好,我是 Kagol,个人公众号:前端开源星球。
TinyEditor 是一个基于 Quill 2.0 的富文本编辑器,在 Quill 基础上扩展了丰富的模块和格式,功能强大、开箱即用。
- 源码:github.com/opentiny/ti…(欢迎 Star ⭐)
- 官网:opentiny.github.io/tiny-editor…
本文是《深入浅出 TinyEditor 富文本编辑器系列》文章的第4篇,主要介绍 TinyEditor 的基础使用示例。
- 深入浅出 TinyEditor 富文本编辑器系列1:TinyEditor 是什么
- 深入浅出 TinyEditor 富文本编辑器系列2:快速开始
- 深入浅出 TinyEditor 富文本编辑器系列3:安装与配置
本文提供了 TinyEditor 入门的综合示例,涵盖了面向初学者开发者的基本实现模式和常见用例。
快速开始实现
初始化 TinyEditor 最基本的方法是通过容器元素和配置选项创建新实例:
import FluentEditor from '@opentiny/fluent-editor'
const editor = new FluentEditor('#editor', {
theme: 'snow',
modules: {
toolbar: [
['bold', 'italic', 'underline'],
['link', 'blockquote'],
[{ list: 'ordered' }, { list: 'bullet' }]
]
}
})
核心架构概述
TinyEditor 扩展了 Quill.js,提供了增强的模块和功能。该架构采用模块化设计,每个功能都作为独立模块实现:
基本配置示例
基本文本编辑器设置
创建带有基本格式化工具的简单文本编辑器:
const basicEditor = new FluentEditor('#editor', {
theme: 'snow',
modules: {
toolbar: [
['undo', 'redo'],
['bold', 'italic', 'strike', 'underline'],
[{ script: 'super' }, { script: 'sub' }],
[{ color: [] }, { background: [] }],
[{ list: 'ordered' }, { list: 'bullet' }],
['link', 'blockquote', 'code-block']
]
}
})
带表格的高级编辑器
对于需要表格功能的更复杂文档:
import { generateTableUp } from '@opentiny/fluent-editor'
import { defaultCustomSelect,TableMenuSelect, TableSelection, TableUp } from 'quill-table-up'
FluentEditor.register({ 'modules/table-up': generateTableUp(TableUp) }, true)
const advancedEditor = new FluentEditor('#editor', {
theme: 'snow',
modules: {
toolbar: [
['undo', 'redo', 'format-painter', 'clean'],
[
{ header: [false, 1, 2, 3, 4, 5, 6] },
{ size: ['12px', '14px', '16px', '18px', '24px', '32px'] },
'bold', 'italic', 'strike', 'underline'
],
[{ color: [] }, { background: [] }],
[{ align: ['', 'center', 'right', 'justify'] }],
[{ 'table-up': [] }],
['link', 'blockquote']
],
'table-up': {
customSelect: defaultCustomSelect,
modules: [
{ module: TableSelection },
{ module: TableMenuSelect },
],
},
}
})
模块配置模式
协同编辑设置
通过 WebSocket provider 启用实时协作:
FluentEditor.register('modules/collaborative-editing', CollaborationModule, true)
const collaborativeEditor = new FluentEditor('#editor', {
theme: 'snow',
modules: {
'collaborative-editing': {
deps: {
Y,
Awareness,
QuillBinding,
QuillCursors,
WebsocketProvider,
IndexeddbPersistence,
},
provider: {
type: 'websocket',
options: {
serverUrl: 'wss://ai.opentiny.design/tiny-editor/',
roomName: ROOM_NAME,
},
},
awareness: {
state: {
name: `userId:${Math.random().toString(36).substring(2, 15)}`,
color: `rgb(${Math.floor(Math.random() * 255)},${Math.floor(Math.random() * 255)},${Math.floor(Math.random() * 255)})`,
},
},
cursors: {
template: `
<span class="${CURSOR_CLASSES.SELECTION_CLASS}"></span>
<span class="${CURSOR_CLASSES.CARET_CONTAINER_CLASS}">
<span class="${CURSOR_CLASSES.CARET_CLASS}"></span>
</span>
<div class="${CURSOR_CLASSES.FLAG_CLASS}">
<small class="${CURSOR_CLASSES.NAME_CLASS}"></small>
</div>
`,
hideDelayMs: 500,
hideSpeedMs: 300,
transformOnTextChange: true,
},
},
}
})
文件上传配置
配置带有自定义 MIME 类型限制的文件上传:
const editorWithUpload = new FluentEditor('#editor', {
theme: 'snow',
modules: {
toolbar: [
['bold', 'italic'],
['image', 'video', 'link']
],
'uploader': {
mimetypes: [
'image/jpeg',
'image/png',
'image/gif',
'application/pdf'
],
handler(range: Range, files: File[]) {
return files.map((_, i) => i % 2 === 0 ? false : 'https://developer.mozilla.org/static/media/chrome.5e791c51c323fbb93c31.svg')
},
fail(file: File, range: Range) {
this.quill.updateContents(new Delta().retain(range.index).delete(1).insert({ image: 'https://developer.mozilla.org/static/media/edge.741dffaf92fcae238b84.svg' }))
},
},
}
})
常见使用场景
内容初始化
创建编辑器时设置初始内容:
const initialContent = `
<h1>Document Title</h1>
<p>This is a <strong>sample</strong> document with <em>formatted</em> text.</p>
<ul>
<li>First item</li>
<li>Second item</li>
</ul>
<blockquote>Important quote here</blockquote>
`
const editor = new FluentEditor('#editor', {
theme: 'snow',
modules: {
toolbar: ['bold', 'italic', 'blockquote']
}
})
// 在初始化后设置内容
editor.clipboard.dangerouslyPasteHTML(0, initialContent)
事件处理
监听编辑器事件以实现自定义功能:
const editor = new FluentEditor('#editor', {
theme: 'snow'
})
// 监听文本变化
editor.on('text-change', (delta, oldDelta, source) => {
console.log('Text changed:', delta)
})
// 监听选择变化
editor.on('selection-change', (range, oldRange, source) => {
if (range) {
console.log('User selected text:', range)
} else {
console.log('User lost focus')
}
})
样式与主题
自定义主题应用
使用 snow 主题应用自定义样式:
const styledEditor = new FluentEditor('#editor', {
theme: 'snow',
modules: {
toolbar: [
[{ header: [1, 2, 3, false] }],
['bold', 'italic', 'underline'],
[{ color: [] }, { background: [] }]
]
},
placeholder: 'Start typing your document...'
})
国际化设置
配置多语言支持:
const i18nEditor = new FluentEditor('#editor', {
theme: 'snow',
modules: {
'i18n': {
lang: 'zh-CN',
fallback: 'en-US'
},
toolbar: ['bold', 'italic', 'link']
}
})
// 动态切换语言
editor.getModule('i18n').setLanguage('en-US')
集成示例
Vue.js 集成
<template>
<div>
<div ref="editorRef" class="editor-container"></div>
</div>
</template>
<script setup>
import { ref, onMounted } from 'vue'
import FluentEditor from '@opentiny/fluent-editor'
const editorRef = ref()
let editor
onMounted(() => {
editor = new FluentEditor(editorRef.value, {
theme: 'snow',
modules: {
toolbar: ['bold', 'italic', 'link']
}
})
})
</script>
React 集成
import { useEffect, useRef } from 'react'
import FluentEditor from '@opentiny/fluent-editor'
function EditorComponent() {
const editorRef = useRef()
const editorInstanceRef = useRef()
useEffect(() => {
editorInstanceRef.current = new FluentEditor(editorRef.current, {
theme: 'snow',
modules: {
toolbar: ['bold', 'italic', 'link']
}
})
return () => {
editorInstanceRef.current = null
}
}, [])
return <div ref={editorRef} className="editor-container" />
}
最佳实践
- 始终指定主题 - 'snow' 主题提供默认 UI
- 配置工具栏模块 - 定义用户可用的工具
- 处理内容初始化 - 在编辑器创建后设置初始内容
- 实现事件监听器 - 响应用户交互和内容变化
- 使用适当的清理 - 卸载组件时销毁编辑器实例
这些示例为使用 TinyEditor 构建复杂的富文本应用程序提供了基础。从基本设置开始,根据需要逐步添加更复杂的功能。
联系我们
GitHub:github.com/opentiny/ti…(欢迎 Star ⭐)
官网:opentiny.github.io/tiny-editor
小助手微信:opentiny-official
公众号:OpenTiny