Tiptap编辑器标题与列表功能失效问题排查
问题分析与修复方案
核心问题1:重复注册Heading扩展
StarterKit已经内置了Heading扩展,你额外单独导入并注册Heading,会导致扩展冲突,直接引发标题功能失效。
核心问题2:缺少基础样式
Tiptap没有默认自带样式,标题、列表等元素需要基础CSS才能正确渲染(比如标题的字号加粗、列表的项目符号),否则即使功能逻辑正常,视觉上也看不到效果。
修复步骤
移除重复的Heading扩展
删掉单独引入的import Heading from '@tiptap/extension-heading';,并从extensions数组中移除Heading,只保留StarterKit即可。添加基础样式
在组件顶部导入Tiptap的基础样式:import '@tiptap/core/style.css'; import '@tiptap/starter-kit/style.css';(可选)自定义Heading配置
如果需要修改Heading的默认行为,比如调整支持的级别,可以在StarterKit里配置:const extensions = [ StarterKit.configure({ heading: { levels: [1, 2, 3] // 只启用h1-h3 } }) ];
修复后的完整代码示例
'use client'; import { EditorContent, useEditor } from '@tiptap/react' import StarterKit from '@tiptap/starter-kit' // 导入基础样式 import '@tiptap/core/style.css'; import '@tiptap/starter-kit/style.css'; const extensions = [ StarterKit ] const content = '' const Tiptap = () => { const editor = useEditor({ extensions, content }) if (!editor) { return null } return ( <div> <div> {/* 工具栏按钮保持不变,添加了margin优化布局 */} <button onClick={() => editor.chain().focus().toggleBold().run()} disabled={!editor.can().chain().focus().toggleBold().run()} className={editor.isActive('bold') ? 'is-active' : ''} style={{ backgroundColor: 'lightgray', color: 'black', padding: '5px 10px', marginRight: '4px' }}>B</button> <button onClick={() => editor.chain().focus().toggleItalic().run()} disabled={!editor.can().chain().focus().toggleItalic().run()} className={editor.isActive('italic') ? 'is-active' : ''} style={{ backgroundColor: 'lightgray', color: 'black', padding: '5px 10px', marginRight: '4px' }} > I </button> <button onClick={() => editor.chain().focus().toggleStrike().run()} disabled={!editor.can().chain().focus().toggleStrike().run()} className={editor.isActive('strike') ? 'is-active' : ''} style={{ backgroundColor: 'lightgray', color: 'black', padding: '5px 10px', marginRight: '4px' }} > S </button> <button onClick={() => editor.chain().focus().toggleCode().run()} disabled={!editor.can().chain().focus().toggleCode().run()} className={editor.isActive('code') ? 'is-active' : ''} style={{ backgroundColor: 'lightgray', color: 'black', padding: '5px 10px', marginRight: '4px' }} > C </button> <button onClick={() => editor.chain().focus().setParagraph().run()} className={editor.isActive('paragraph') ? 'is-active' : ''} style={{ backgroundColor: 'lightgray', color: 'black', padding: '5px 10px', marginRight: '4px' }} > P </button> <button onClick={() => editor.chain().focus().toggleHeading({ level: 1 }).run()} className={editor.isActive('heading', { level: 1 }) ? 'is-active' : ''} style={{ backgroundColor: 'lightgray', color: 'black', padding: '5px 10px', marginRight: '4px' }} > h1 </button> <button onClick={() => editor.chain().focus().toggleHeading({ level: 2 }).run()} className={editor.isActive('heading', { level: 2 }) ? 'is-active' : ''} style={{ backgroundColor: 'lightgray', color: 'black', padding: '5px 10px', marginRight: '4px' }} > h2 </button> <button onClick={() => editor.chain().focus().toggleHeading({ level: 3 }).run()} className={editor.isActive('heading', { level: 3 }) ? 'is-active' : ''} style={{ backgroundColor: 'lightgray', color: 'black', padding: '5px 10px', marginRight: '4px' }} > h3 </button> <button onClick={() => editor.chain().focus().toggleBulletList().run()} className={editor.isActive('bulletList') ? 'is-active' : ''} style={{ backgroundColor: 'lightgray', color: 'black', padding: '5px 10px', marginRight: '4px' }} > bullet list </button> <button onClick={() => editor.chain().focus().toggleOrderedList().run()} className={editor.isActive('orderedList') ? 'is-active' : ''} style={{ backgroundColor: 'lightgray', color: 'black', padding: '5px 10px', marginRight: '4px' }} > ordered list </button> <button onClick={() => editor.chain().focus().toggleCodeBlock().run()} className={editor.isActive('codeBlock') ? 'is-active' : ''} style={{ backgroundColor: 'lightgray', color: 'black', padding: '5px 10px', marginRight: '4px' }} > code block </button> <button onClick={() => editor.chain().focus().toggleBlockquote().run()} className={editor.isActive('blockquote') ? 'is-active' : ''} style={{ backgroundColor: 'lightgray', color: 'black', padding: '5px 10px', marginRight: '4px' }} > blockquote </button> <button onClick={() => editor.chain().focus().setHorizontalRule().run()} style={{ backgroundColor: 'lightgray', color: 'black', padding: '5px 10px', marginRight: '4px' }}> horizontal rule </button> <button onClick={() => editor.chain().focus().setHardBreak().run()} style={{ backgroundColor: 'lightgray', color: 'black', padding: '5px 10px', marginRight: '4px' }}> hard break </button> <button onClick={() => editor.chain().focus().undo().run()} disabled={!editor.can().chain().focus().undo().run()} style={{ backgroundColor: 'lightgray', color: 'black', padding: '5px 10px', marginRight: '4px' }} > undo </button> <button onClick={() => editor.chain().focus().redo().run()} disabled={!editor.can().chain().focus().redo().run()} style={{ backgroundColor: 'lightgray', color: 'black', padding: '5px 10px' }} > redo </button> </div> <div style={{ marginTop: '12px', padding: '8px', border: '1px solid #eee' }}> <EditorContent editor={editor}/> </div> </div> ) } export default Tiptap
内容的提问来源于stack exchange,提问作者YoBoz
相关产品推荐
相关产品推荐

