Skip to content

富文本编辑器

qxs-blocksuite-editor 是基于 BlockSuite PageEditor 封装的 Web Component 富文本编辑器,支持常显顶部工具栏、Slash 命令、图片上传、Markdown 输入输出和结构化内容事件。

富文本编辑器接入

这页先解决“编辑器怎么接起来”,再去区分工具栏模式、内容格式、图片上传和预览态。
先跑通一个完整 demo,会比先看字段更容易理解 contentcontent-formatcontent-updatepreview 的关系。

loading

基础用法

ts
import '@qxs-bns/components/editor'

使用说明

什么时候选 header,什么时候选 slash

toolbar-mode="header" 更适合后台表单、题目描述等固定编辑区域;
toolbar-mode="slash" 更接近 Notion 式输入体验,适合正文创作。

Vue 宿主里的对象、数组、函数和布尔值

toolbarheader-toolbar-labelsupload-imagereadonlypreviewuse-modeldeserialize-content 这类字段,Vue 里建议使用 .prop 透传。
例如 :toolbar.prop="toolbar":header-toolbar-labels.prop="headerToolbarLabels":preview.prop="true":upload-image.prop="uploadFn"

contentmodel-value 的关系

默认使用 content 作为内容输入。
如果你希望走 v-model 风格的 model-value,需要同时开启 use-model

常见场景

最小接入

html
<script type="module">
  import '@qxs-bns/components/editor'
</script>

<qxs-blocksuite-editor content="<p>初始内容</p>"></qxs-blocksuite-editor>

显式切换到 Slash 模式

html
<qxs-blocksuite-editor
  toolbar-mode="slash"
  content="<p>输入 / 唤出快捷命令</p>"
></qxs-blocksuite-editor>

直接以 Markdown 作为宿主内容格式

html
<qxs-blocksuite-editor
  toolbar-mode="slash"
  toolbar-preset="simple"
  content-format="markdown"
  content="## 标题\n\n- 第一项\n- 第二项"
></qxs-blocksuite-editor>

Header 工具栏默认常显,并可按需覆盖按钮文案

vue
<script setup lang="ts">
const toolbar = ['table', 'list', 'link', 'format', 'image']

const headerToolbarLabels = {
  image: '插入图片',
  link: '插入链接',
}
</script>

<template>
  <qxs-blocksuite-editor
    :toolbar.prop="toolbar"
    :header-toolbar-labels.prop="headerToolbarLabels"
  />
</template>

toolbar 现在不仅控制显示哪些工具项,也会直接决定这些工具项在 header / slash 工具栏中的渲染顺序。
例如上面的配置会把 表格 -> 列表 -> 链接 -> 格式组 -> 图片 排到前面,并把图片按钮固定到最后。

如果你希望回退成“聚焦后再展示 header”,可以显式传入 :header-always-visible.prop="false"

自定义图片上传

vue
<script setup lang="ts">
const uploadImage = async (file: File) => {
  const formData = new FormData()
  formData.append('file', file)

  const res = await fetch('/api/upload', {
    method: 'POST',
    body: formData,
  })

  const data = await res.json()
  return data.url
}
</script>

<template>
  <qxs-blocksuite-editor :upload-image.prop="uploadImage" />
</template>

API

属性

NameDescriptionTypeDefault
content编辑器 HTML 内容string''
model-value搭配 use-model 使用的内容值string''
placeholder占位文案string'输入内容'
toolbar-mode工具栏模式'header' | 'slash''header'
toolbar-preset内置工具栏预设;未传 toolbar 时生效'full' | 'simple' | 'none''full'
header-toolbar-labels仅在 header 模式下生效的按钮文案映射;支持对象或 JSON 字符串Partial<Record<'bold' | 'italic' | 'underline' | 'strike' | 'code' | 'link' | 'image' | 'bulletList' | 'orderedList' | 'taskList' | 'blockquote' | 'table', string>> | string{ image: '插入图片', link: '插入链接' }
header-always-visible是否始终显示顶部工具栏booleantrue
use-model是否改用 model-value 作为内容输入源booleanfalse
readonly只读模式booleanfalse
preview预览模式,隐藏边框和编辑工具栏booleanfalse
editable显式控制是否可编辑,优先级高于 readonlybooleannull
min-height编辑区最小高度string'80px'
max-height编辑区最大高度;传入后内容区自动滚动string''
show-character-count是否展示字符统计booleanfalse
toolbar-position顶部工具栏显示在上方还是下方'top' | 'bottom''top'
custom-styles注入到 Shadow DOM 的额外样式文本string''
content-format宿主内容格式;未传转换函数时决定内置序列化行为'html' | 'markdown' | 'custom''html'
deserialize-content自定义输入转换函数,优先级高于 content-format(value: string) => string-
serialize-content自定义输出转换函数,优先级高于 content-format(value: string) => string-
upload-image自定义图片上传函数,返回最终图片 URL(file: File) => Promise<string>base64

事件

NameDescriptionType
content-update推荐使用的结构化内容事件,返回 { value, html, text, format }(snapshot: ContentSnapshot) => void
content-change兼容事件,仅返回宿主格式下的 value 字符串(value: string) => void
image-upload-error图片上传失败时触发,返回 { file, error }(detail: { file: File; error: Error }) => void

方法

NameDescriptionType
getContent()获取当前宿主格式下的内容字符串() => string
getContentSnapshot()获取结构化内容快照 { value, html, text, format }() => ContentSnapshot

常见问题

previewreadonly 有什么区别?

  • readonly 仍保留编辑器外观,但不可编辑。
  • preview 会进一步关闭编辑器边框和工具栏,更适合最终展示。

我应该监听 content-change 还是 content-update

新接入建议优先监听 content-update
它会同时给出:

  • value: 当前宿主格式的值
  • html: 编辑器内部 HTML
  • text: 纯文本
  • format: 当前内容格式

content-change 仍然保留,用来兼容旧代码。

富文本编辑器 has loaded