TOAST UI Editor 工具栏定制完全指南:从默认选项到自定义按钮与状态联动

发布时间:2026/9/21 16:15:34
TOAST UI Editor 工具栏定制完全指南:从默认选项到自定义按钮与状态联动 TOAST UI Editor 工具栏定制完全指南从默认选项到自定义按钮与状态联动【免费下载链接】tui.editor Markdown WYSIWYG Editor. GFM Standard Chart UML Extensible.项目地址: https://gitcode.com/gh_mirrors/tu/tui.editorTOAST UI Editor以下简称“编辑器”以 Markdown 与 WYSIWYG 双模式为核心而工具栏正是这两类编辑体验的交互枢纽在 Markdown 语法不直观的所见即所得模式中绝大多数操作都依赖工具栏完成。本文将围绕官方文档《Toolbar》展开完整讲解toolbarItems二维数组配置、内建按钮定制、popup弹层选项、el自定义元素、state状态联动与onUpdated回调并深入仓库源码验证其底层实现帮助你掌握从“组合默认按钮”到“编写完整自定义工具栏插件”的全套能力。工具栏选项Toolbar Option编辑器内置了 bold、italic、strike 等总计 16 种工具栏元素。在不指定任何选项时默认工具栏配置如下const options { // ... toolbarItems: [ [heading, bold, italic, strike], [hr, quote], [ul, ol, task, indent, outdent], [table, image, link], [code, codeblock], [scrollSync], ], }从示例代码可以看到编辑器的工具栏选项以二维数组的形式定义第一层数组的每个元素是一个工具栏分组group分组内的工具栏元素则作为内层数组的元素。各元素按照定义顺序在分组内渲染而工具栏分组之间以|分隔线符号隔开渲染。16 种内建工具栏元素速查结合 toolbarItemFactory.ts 中的createDefaultToolbarItemInfo实现默认支持的 16 种元素及其默认绑定的命令、tooltip 与 state 如下表所示元素名默认命令command默认 tooltipen状态stateheading弹层插入标题HeadingsheadingboldboldBoldstrongitalicitalicItalicemphstrikestrikeStrikestrikehrhrLinethematicBreakquoteblockQuoteBlockquoteblockQuoteulbulletListUnordered listbulletListolorderedListOrdered listorderedListtasktaskListTasktaskListtable弹层插入表格Insert tabletableimage弹层插入图片Insert image—link弹层插入链接Insert link—codecodeCodecodecodeblockcodeBlockInsert CodeBlockcodeBlockindentindentIndentindentoutdentoutdentOutdentoutdentscrollSynctoggleScrollSync——注scrollSync是一个特殊的切换式元素其内部渲染为复选框 开关switch而非按钮相关实现见 toolbarItemFactory.ts同时它并非总是显示——当编辑器处于 WYSIWYG 模式或预览样式为tab时scrollSync会被隐藏见 toolbar.ts。此外超过一行显示宽度的元素会自动收进 “More更多” 下拉工具栏中见 toolbar.ts。重新组合默认工具栏如果想修改默认工具栏的构成只需在创建编辑器时传入toolbarItems选项const editor new Editor({ el: document.querySelector(#editor), toolbarItems: [ [heading, bold], [ul, ol, task], [code, codeblock], ], });执行上面的示例代码后工具栏会按新配置渲染为三个分组。从源码上看toolbarItems的类型为(string | ToolbarItemOptions)[][]见 editor.d.ts即每个元素既可以是内建按钮的字符串名称也可以是一个自定义选项对象——这正是接下来要讲的定制入口。工具栏按钮定制Toolbar Button Customizing单纯组合默认元素只能满足基础需求。当需要自己创建并添加工具栏按钮时编辑器提供两大类型的定制选项一是复用内建按钮 UI仅重定义图标、tooltip 或弹层行为二是完全自定义 DOM 元素。内建按钮元素定制Button Element Customizing这种方式仍然使用编辑器内建的按钮渲染逻辑只覆盖按钮的图标、tooltip 或 popup 行为。对应的选项接口如下名称类型说明namestring工具栏元素的唯一名称必填。tooltipstring可选。鼠标悬停在工具栏元素上时显示的提示文字。textstring可选。需要在工具栏按钮元素上显示的文本。classNamestring可选。应用到工具栏元素上的 class。styleObject可选。应用到工具栏元素上的行内样式。commandstring可选。点击工具栏按钮时要执行的命令。与popup选项互斥。popupPopupOptions可选。点击工具栏按钮时希望弹出的弹层。与command选项互斥。const editor new Editor({ el: document.querySelector(#editor), toolbarItems: [ [{ name: myItem, tooltip: myItem, command: bold, text: , className: toastui-editor-toolbar-icons, style: { backgroundImage: none, color: red } }] ], // ... });运行上面的示例后会生成一个同时应用了className与style的工具栏按钮按钮包含文本节点点击时执行bold命令。从实现层面看这类定制走的是 toolbarButton.ts 中的ToolbarButtonComp按钮渲染为button元素text作为按钮文本className与style直接拼入 class 与行内样式点击时如果存在command就调用execCommand(command)否则走弹层分支createPopupInfo见 toolbarButton.ts。需要特别注意的是text只影响按钮文本而不会替换图标字体示例中通过backgroundImage: none去掉图标字体背景、再用文本代替图标是一种常见的定制手法。popup 选项自定义弹层如果希望点击按钮时不是执行命令而是弹出自己定义的弹层则使用popup选项。其接口如下名称类型说明bodyHTMLElement要渲染的弹层 DOM 节点必填。classNamestring可选。应用到弹层元素上的 class。styleObject可选。应用到弹层元素上的样式。配置好的弹层节点会在点击工具栏时自动显示在屏幕上点击其他区域时自动消失。以编辑器的 color-syntax颜色选择插件代码为参考对应仓库实现见 color-syntax/src/index.ts 与 index.tsconst container document.createElement(div); // ... const button createApplyButton(i18n.get(OK)); button.addEventListener(click, () { // ... eventEmitter.emit(command, color, { selectedColor }); eventEmitter.emit(closePopup); }); container.appendChild(button); const colorPickerToolber { name: color, tooltip: Text color, className: some class, popup: { className: some class, body: container, style: { width: auto }, }, };示例代码将弹层要展示的元素放入变量container。该元素包含一个按钮点击时执行color命令并关闭弹层。这里展示了自定义弹层与编辑器通信的两条关键途径需要执行命令时通过eventEmitter.emit(command, color, { selectedColor })发出command事件需要关闭弹层时发出closePopup事件。从底层实现看自定义弹层最终会渲染为CustomPopupBody由createPopupInfo(customPopupBody, ...)处理见 toolbarItemFactory.ts而弹层的打开/关闭状态由 Toolbar 组件的showPopup状态统一管理点击弹层外部区域会触发hidePopup见 toolbar.ts。color-syntax 插件的完整示例可对照 color-syntax 插件源码 学习。工具栏元素定制Toolbar Item Customizing如果不使用内建按钮 UI而是希望完全自己控制渲染元素则需要指定el选项const myCustomEl document.createElement(span); myCustomEl.textContent ; myCustomEl.style cursor: pointer; background: red; myCustomEl.addEventListener(click, () { editor.exec(bold); }); const editor new Editor({ el: document.querySelector(#editor), toolbarItems: [ [{ name: myItem, tooltip: myItem, el: myCustomEl, }] ], // ... });由于el选项接收的是一个完整的 DOM 元素因此点击行为、style、class 等都必须由开发者自行设置。运行示例后工具栏会渲染出自定义的元素点击执行bold命令。在实现上带el的工具栏项会渲染为CustomToolbarItem它把自定义元素appendChild进一个带toolbar-item-wrapperclass 的容器中并自动为其挂上 tooltip 与 popup 事件监听见 customToolbarItem.ts。分组渲染时ToolbarGroup会依据“是否存在el”来区分渲染CustomToolbarItem还是ToolbarButton见 toolbarGroup.ts。除el外ToolbarCustomOptions还额外支持hidden、onMounted两个仅在自定义元素下可用的选项见 ui.d.ts其中onMounted(execCommand)会在元素挂载完成后被调用可用来绑定需要执行命令的复杂交互如 scrollSync 元素的自定义复选框逻辑见 toolbarItemFactory.ts。工具栏状态变更Change Toolbar Item State编辑器可以根据当前光标所在位置对应的节点类型通过改变工具栏元素样式来“点亮”对应按钮。例如当光标位于加粗文本strong节点上时bold工具栏元素会被激活追加active类。若希望自定义的工具栏元素也能随光标位置切换状态则需要配置state选项const editor new Editor({ el: document.querySelector(#editor), toolbarItems: [ [{ name: myItem, tooltip: myItem, command: bold, text: , className: toastui-editor-toolbar-icons, style: { backgroundImage: none, color: red }, // 光标位于 strong 节点时该工具栏元素会被追加 active 类 state: strong, }] ], // ... });当工具栏按钮依据state被激活时编辑器会为其追加activeCSS 类之后即可基于该类编写自定义激活样式。按钮激活类拼接发生在 toolbarButton.ts${item.className || }${active ? active : }。state 列表只有使用下列 state 值才能改变工具栏元素的激活状态heading标题strong加粗emph斜体strike删除线thematicBreak水平分隔线blockQuote引用块bulletList无序列表orderedList有序列表taskList任务列表table表格code行内代码codeBlock代码块从类型定义看state的类型是ToolbarStateKeys即上述键的联合类型同时底层状态映射ToolbarStateMap还额外包含indent、outdent两项见 ui.d.ts与默认元素indent/outdent一一对应。状态联动的底层原理工具栏状态不是凭空产生的而是由 WYSIWYG 编辑器内的 ProseMirror 插件实时计算并广播的。在 toolbarState.ts 中toolbarStateHighlight插件在每次文档选择selection更新时调用getToolbarState(selection, doc, schema)遍历光标范围内的节点位于listItem时根据node.attrs.task判定为taskList或父级列表类型节点类型包含table时归一化为table对strong、strike、emph、code四种 mark 类型检查选区两侧是否存在对应 mark其余节点类型直接作为 state 键标记为{ active: true }。计算结果通过eventEmitter.emit(changeToolbarState, { toolbarState })广播出去。而在 UI 侧buttonHoc.ts 中每个带state的按钮都会listen(changeToolbarState)从toolbarState[item.state]中取出{ active, disabled }并更新自身状态——这就是光标移动时按钮实时点亮的完整调用链。onUpdated() 选项自定义元素的状态回调使用el选项创建工具栏元素时由于编辑器无法直接操纵你传入的 DOM必须借助onUpdated回调来响应状态变化const myCustomEl document.createElement(span); myCustomEl.textContent ; myCustomEl.style cursor: pointer; background: red; myCustomEl.addEventListener(click, () { editor.exec(bold); }); const editor new Editor({ el: document.querySelector(#editor), toolbarItems: [ [{ name: myItem, tooltip: myItem, el: myCustomEl, state: strong, onUpdated({ active, disabled }) { if (active) { myCustomEl.style.background green; } else { myCustomEl.style.background ; } } }] ], // ... });onUpdated()接收一个包含active、disabled状态的对象作为参数可据此为元素追加样式或定义任意行为。其触发时机在 customToolbarItem.ts当active或disabled与前一次渲染不同时调用item.onUpdated?.({ active, disabled })。注意disabled与active可能同时出现例如列表内indent/outdent的禁用态状态对象类型见 ui.d.ts。动态增删工具栏项insertToolbarItem 与 removeToolbarItem除初始化配置外编辑器还提供了运行时 APIeditor.insertToolbarItem({ groupIndex, itemIndex }, item)向指定分组的指定位置插入一个工具栏项字符串或选项对象editor.removeToolbarItem(itemName)按name移除工具栏项。两个 API 的类型声明见 editor.d.ts实现位于 toolbar.tsinsertToolbarItem会先通过createToolbarItemInfo把字符串规范化为选项对象再在对应分组splice插入若分组索引越界则新建分组。结合 example15-customizing-toolbar-buttons.html 可以看到完整用法——该示例在初始化工具栏后又通过insertToolbarItem在第一个分组的最前面动态插入了一个自定义的按钮并配合firstclass 实现红色样式。完整实战示例官方提供了可运行的示例 example15-customizing-toolbar-buttons.html其中综合展示了三种定制手段function createLastButton() { const button document.createElement(button); button.className toastui-editor-toolbar-icons last; button.style.backgroundImage none; button.style.margin 0; button.innerHTML iB/i; button.addEventListener(click, () { editor.exec(bold); }); return button; } const editor new toastui.Editor({ el: document.querySelector(#editor), previewStyle: vertical, height: 500px, initialValue: The first and last buttons are customized., toolbarItems: [ [heading, bold, italic, strike], [hr, quote], [ul, ol, task, indent, outdent], [table, image, link], [code, codeblock], // 用 el 选项定制“最后一个”按钮 [{ el: createLastButton(), command: bold, tooltip: Custom Bold }] ] }); editor.insertToolbarItem({ groupIndex: 0, itemIndex: 0 }, { name: myItem, tooltip: Custom Button, command: bold, text: , className: toastui-editor-toolbar-icons first, style: { backgroundImage: none } });该示例在编辑器初始化后动态插入“第一个”按钮使用insertToolbarItem并在toolbarItems中配置了“最后一个”按钮使用el自定义元素配合样式表中.toastui-editor-defaultUI button.first { color: red; }与.last { color: orange; }的定制样式直观演示了本节所有 API 的组合用法。小结工具栏是 TOAST UI Editor 中交互密度最高的组件。通过toolbarItems二维数组可以自由重组 16 种内建元素通过command/popup选项可以复用内建按钮 UI 定制点击行为通过el选项可以完全接管渲染元素通过stateonUpdated可以实现随光标位置实时点亮的动态状态再配合insertToolbarItem/removeToolbarItem两个运行时 API即可打造出高度贴合业务场景的定制工具栏。【免费下载链接】tui.editor Markdown WYSIWYG Editor. GFM Standard Chart UML Extensible.项目地址: https://gitcode.com/gh_mirrors/tu/tui.editor创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考