BlockSuite Note Block 深入解析:从页面文档容器到画布白板便签

发布时间:2026/9/17 9:54:01
BlockSuite Note Block 深入解析:从页面文档容器到画布白板便签 BlockSuite Note Block 深入解析从页面文档容器到画布白板便签【免费下载链接】blocksuite Content editing tech stack for the web - BlockSuite is a toolkit for building editors and collaborative applications.项目地址: https://gitcode.com/GitHub_Trending/bl/blocksuiteBlockSuite 中的 Note Blockaffine:note是一个承载流式文档内容的容器块它既是页面Doc编辑器中全部正文的唯一宿主也是画布Edgeless编辑器中可自由摆放、拆分的便签卡片。本文以 note-block.md 为骨架结合 note-model.ts、note-block.ts、note-edgeless-block.ts 等源码实现完整讲解 Note Block 的定位、xywh/index定位机制、显示模式、组件与服务层以及键盘交互帮助你在自己的编辑器中正确使用与定制该块。BlockSuite 页面区块嵌套关系示意图Note Block 是什么官方文档给出的定义非常简洁Note Block 是用于放置流式文档内容flowing document content的容器块container block。所谓流式内容指的是段落、列表、代码块这类按文档流顺序排列、自上而下排版的块。与之相对的是画布上的图形元素shape、connector 等它们由 Surface Block 负责渲染不参与文档流。从块树结构看Note Block 的嵌套关系是Page Blockroot ├── Surface Block可选用于图形编辑 └── Note Block ├── Paragraph Block │ └── Paragraph Block ├── Paragraph Block └── ...上图清晰地展示了这一层级Note Block 位于 Page Block 之下其内部再承载多个 Paragraph Block。文档中的block-nesting示意图block-nesting.png即用于说明这一结构。Note Block 在两种编辑器中的不同角色BlockSuite 提供两种编辑器Note Block 在其中的行为截然不同参见 page-editor.md 与 edgeless-editor.md页面Doc编辑器中唯一的正文容器如果一份文档完全在页面编辑器中编辑那么它的全部文本内容都会放置在一个 Note Block 中。此时 Note Block 承担的是传统富文本编辑器如 ProseMirror、Slate中正文区的角色——用户的输入、粘贴的内容、插入的图片/数据库等块都作为 Note Block 的子块存在。在页面编辑器中Note Block 的显示顺序由它在根块Page Blockchildren数组中的排列顺序决定。也就是说它是纯文档流式的先出现的 Note 排上面后出现的排下面。画布Edgeless编辑器中可自由摆放与拆分的便签在画布编辑器中情况完全不同画布允许放置多个 Note Block每个便签都可以被拖动、缩放、设置背景色和阴影画布还支持将一个 Note Block 的内容拆分成多个不同的 Note例如通过工具栏或拖拽把一部分子块移出每个 Note Block 的位置由xywh字段决定与其它图形内容的层叠关系由index字段决定从而可以和 shape、connector、frame 等图形元素一起被自由定位在无限画布上。值得强调的是BlockSuite 的两种编辑器可以绑定同一个 doc 对象见 page-editor.md 的 runtime compatibility 说明因此同一份数据既能以流式 Note 呈现也能以画布便签呈现。Schema 与模型层源码级的定位与属性定义Note Block 的 Schema 定义在 note-model.tsflavour 为affine:note。通过defineBlockSchema声明了默认属性与块元数据export const NoteBlockSchema defineBlockSchema({ flavour: affine:note, props: (): NoteProps ({ xywh: [0,0,${NOTE_WIDTH},95], // 默认宽 800高 95 background: DEFAULT_NOTE_BACKGROUND_COLOR, // 默认蓝色背景 index: a0, hidden: false, // 已废弃改用 displayMode displayMode: NoteDisplayMode.DocAndEdgeless, edgeless: { style: { borderRadius: 0, borderSize: 4, borderStyle: StrokeStyle.None, shadowType: DEFAULT_NOTE_SHADOW, }, }, }), metadata: { version: 1, role: hub, parent: [affine:page], children: [ affine:paragraph, affine:list, affine:code, affine:divider, affine:database, affine:data-view, affine:image, affine:bookmark, affine:attachment, affine:surface-ref, affine:embed-*, ], }, toModel: () new NoteBlockModel(), });这里的几个关键点role: hub表明 Note Block 是一个枢纽型容器负责组织其下所有内容块这与文档中container block的定位完全对应。parent: [affine:page]Note Block 只能作为 Page Block 的直接子节点。children列表Note Block 允许承载段落、列表、代码、分割线、数据库、数据视图、图片、书签、附件、surface-ref 以及所有affine:embed-*嵌入类块——这解释了为什么它是所有文本内容的唯一宿主。xywh字段画布上的几何定位xywh是SerializedXYWH类型形如[x,y,w,h]的序列化字符串。默认值为[0,0,800,95]其中NOTE_WIDTH 800定义在 consts/note.ts。在画布编辑器中x、y表示 Note 左上角在画布坐标系中的位置w、h表示便签的宽高组件通过Bound.deserialize(this.model.xywh)将其解析为几何矩形用于渲染、命中测试和拖拽。从源码结构看Note Block 的模型类NoteBlockModel继承自GfxCompatible(BlockModel)并实现GfxElementGeometry接口见 note-model.ts因此它天然拥有containsBound、includesPoint、intersectsBound等几何能力可以被画布选择框、套索、吸附等图形系统识别。注意当displayMode NoteDisplayMode.DocOnly时_isSelectable()返回 false画布上的几何命中会被禁用。index字段画布上的层叠顺序index是 Gfx 层layer系统中用于确定元素 z 轴顺序的字符串键默认值为a0。在画布编辑器中Note Block 与 shape、connector 等图形元素统一参与index排序渲染时通过this.rootService.layer.getZIndex(this.model)计算 z-index见 note-edgeless-block.ts。正因如此便签才能和图形内容互相覆盖、自由叠放。显示模式displayMode 与 hiddendisplayMode是 Note Block 最重要的显示控制属性类型为NoteDisplayMode枚举定义在 consts/note.ts枚举值字符串值含义DocAndEdgelessboth在页面编辑器和画布编辑器中都显示默认值DocOnlydoc仅在页面编辑器中显示EdgelessOnlyedgeless仅在画布编辑器中显示模型源码中标注了hidden属性已废弃并给出了迁移映射hidden: true→displayMode: NoteDisplayMode.EdgelessOnly仅在画布模式可见hidden: false→displayMode: NoteDisplayMode.DocAndEdgeless两种模式均可见。这一设计允许同一份文档在纯文档视图和画布视图下展示不同的 Note 集合例如在画布上补充批注便签而页面视图中不显示它。EdgelessNoteBlockComponent的渲染逻辑也据此分支当displayMode NoteDisplayMode.DocOnly时直接返回空见 note-edgeless-block.ts。画布便签的视觉样式属性edgeless.style对象控制便签在画布上的外观默认值见 note-model.tsborderRadius圆角半径默认 0borderSize边框粗细默认 4borderStyle边框样式StrokeStyle枚举取值dash/none/solid默认none即无边框shadowType阴影类型可选值定义在 consts/note.ts空字符串无阴影、--affine-note-shadow-box、--affine-note-shadow-sticker默认、--affine-note-shadow-paper、--affine-note-shadow-float、--affine-note-shadow-film。此外还有collapse、collapsedHeight、scale三个扩展属性scale控制便签内容的缩放collapse与collapsedHeight用于折叠便签——折叠后只显示固定高度悬停或拖拽时通过底部折叠按钮展开见 note-edgeless-block.ts。背景色由background属性控制默认值NOTE_BACKGROUND_COLORS[5]即蓝色完整的 11 种色板同样定义在 consts/note.ts。组件与服务双视图与统一服务两种视图组件BlockSpec 中为 Note Block 注册了两个视图组件见 note-spec.tsNoteBlockSpec页面编辑器视图渲染affine-note自定义元素即 note-block.ts 中的NoteBlockComponent。它的渲染逻辑非常直接一个flow-root容器内部调用this.renderChildren(this.model)渲染所有子块选中时叠加--affine-hover-color背景EdgelessNoteBlockSpec画布编辑器视图渲染affine-edgeless-note即 note-edgeless-block.ts 中的EdgelessNoteBlockComponent。它通过toGfxBlockComponent(NoteBlockComponent)复用页面版组件并叠加画布能力背景层note-background、内容裁剪容器overflow-y: clip、折叠按钮、edgeless-note-mask交互遮罩等。画布版组件还会自动根据内容高度同步xywh通过ResizeObserver监听内容尺寸变化将bound.h更新为实际内容高度见 note-edgeless-block.ts。也就是说在画布中Note 的默认高度是自适应内容而非固定 95。同时点击便签空白区域时组件会就近计算插入位置并自动addSiblingBlocks补一个段落块保证点击处可以直接开始输入见 note-edgeless-block.ts。NoteBlockService命令与拖拽能力NoteBlockServicenote-service.ts继承BlockServiceNoteBlockModel在mounted()时注册两类能力快捷键绑定Tab/Shift-Tab分别执行indentBlocks/dedentBlocks命令用于调整光标所在块的缩进层级拖拽手柄Drag Handle选项当从 Note 的拖拽手柄开始拖拽时生成便签的实时预览renderModel渲染 Bound偏移计算支持把整个 Note 拖出画布拖拽结束落点不在 Note 内部时——若按住Alt则复制Note 的全部子块插入目标位置否则移动子块到目标块并删除原 Note见 note-service.ts。这正是将一个 Note 拆分成多个 Note的底层实现路径之一。KeymapController块级键盘交互页面版组件在connectedCallback中绑定 keymap-controller.ts见 note-block.ts它基于 BlockSuite 的命令链系统处理 Note 内部的键盘事件ArrowDown / ArrowUp在文本选区与块选区之间智能导航。若下一个块是 paragraph/list/code 则沿用默认文本行为否则切换为块选区selectBlockShift-ArrowDown / Shift-ArrowUp基于锚点块anchor block连续多选块selectBlocksBetween并保证焦点块始终停留在当前 Note 容器内Enter在块选区下于当前块后插入新的 paragraph 并聚焦Escape清除块选区回到文本编辑状态Mod-a在 Note 内部全选所有子块另外还批量注册了移动块、快速操作quick action与文本类型转换如段落转代码块等配置热键。从实现上看KeymapController把Note 内块导航这一复杂交互完全收敛到容器组件内用户无需关心块级边界体验上接近单一文档流。如何在实际项目中使用由于 Note Block 是页面编辑器的默认正文容器在常规使用中你几乎不需要手动创建它——初始化 doc 并绑定 PageEditor 后正文会自动落在 Note Block 中。以下场景需要你主动关注它构建纯页面编辑器使用NoteBlockSpec文档只有一个 Note全部内容按文档流排版构建白板应用使用EdgelessNoteBlockSpec通过修改模型的xywh摆放多个便签用index控制层叠用displayMode控制便签是否在页面视图中出现拆分便签借助 Note 的拖拽手柄或编程方式doc.moveBlocks/doc.addBlocks将一个 Note 的子块迁移到另一个 Note。如果你想在自己的 BlockSuite 应用中定制 Note Block 行为可以从这几处入手note-spec.ts注册视图组件、note-model.ts默认属性与子块白名单、note-service.ts服务与拖拽选项、note-edgeless-block.ts画布渲染细节。参考官方文档note-block.md、page-editor.md、edgeless-editor.mdSchema 与模型note-model.ts、note.ts组件与服务note-block.ts、note-edgeless-block.ts、note-service.ts、keymap-controller.ts、note-spec.ts嵌套结构示意图block-nesting.png【免费下载链接】blocksuite Content editing tech stack for the web - BlockSuite is a toolkit for building editors and collaborative applications.项目地址: https://gitcode.com/GitHub_Trending/bl/blocksuite创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询