You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Tiptap编辑器标题与列表功能失效问题排查

问题分析与修复方案

核心问题1:重复注册Heading扩展

StarterKit已经内置了Heading扩展,你额外单独导入并注册Heading,会导致扩展冲突,直接引发标题功能失效。

核心问题2:缺少基础样式

Tiptap没有默认自带样式,标题、列表等元素需要基础CSS才能正确渲染(比如标题的字号加粗、列表的项目符号),否则即使功能逻辑正常,视觉上也看不到效果。


修复步骤

  1. 移除重复的Heading扩展
    删掉单独引入的import Heading from '@tiptap/extension-heading';,并从extensions数组中移除Heading,只保留StarterKit即可。

  2. 添加基础样式
    在组件顶部导入Tiptap的基础样式:

    import '@tiptap/core/style.css';
    import '@tiptap/starter-kit/style.css';
    
  3. (可选)自定义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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 06:44:50