# 连接工具栏与编辑器

从加粗按钮开始，理解命令、可用状态和界面更新。

工作区已经能输入了。现在加一个“加粗”按钮：选中文字，点击按钮，让 Core 修改这段内容，再让按钮显示当前是否加粗。

界面不需要自己修改正文 JSON。按钮、快捷键和应用代码都调用同一个 Editor 的命令。

## 1. 执行一个动作

```ts [加粗按钮的点击处理]
editor.chain().focus().toggleBold().run()
```

`focus()` 把输入焦点交回编辑器，`toggleBold()` 修改当前选区，`run()` 提交命令链。使用当前选区即可，不必先移动到文档末尾。

直接执行单个动作可以调用 `editor.commands.toggleBold()`。当你要把焦点、插入、格式等几个动作组合起来时，使用 `chain()` 更方便。

## 2. 区分选中和禁用

按钮需要回答两个不同的问题：当前文字是不是粗体？现在可不可以执行加粗？

```ts [普通 Bold 扩展的按钮状态]
const active = editor.isActive('bold')
const enabled = editor.isEditable && editor.can().toggleBold()
```

`isActive()` 查询格式，`can()` 检查能否执行但不修改内容。只读切换还应调用 `editor.setEditable(false)`，让视图停止接受用户编辑输入；只禁用按钮不能禁止键盘输入。程序命令的写权限仍由应用检查，见[命令与事务](/concepts/commands)。

Word 格式还可能继承段落样式，所以它的状态查询不同。完整示例的 `assembly/word.ts` 使用 `readEffectiveDirectEmphasisState()` 读取实际加粗状态，而普通模型使用 `isActive('bold')`。按钮的显示逻辑应与安装的格式扩展配套。

## 3. 内容改变后更新按钮

保存一个 Editor 实例，只把按钮需要的布尔值交给 Vue。订阅 `transaction` 后重新读取这些状态，在组件退出时移除同一个监听函数。

```ts [订阅与释放]
editor.on('transaction', refreshToolbar)
// 组件退出时：
editor.off('transaction', refreshToolbar)
```

`refreshToolbar` 是你自己的状态更新函数。通常读取加粗、撤销、重做等少量状态就够了，不必在每次光标移动时调用 `getJSON()` 复制全文。保存中的提示、文件错误和页数也分别由保存流程与 View 更新。

## 在完整工程里找哪里

`workspace.vue` 放按钮和点击处理；`session.ts` 计算并发布按钮状态；`assembly/` 提供与文档模型匹配的格式查询。可以在[工程参考](/build/reference)中逐个查看。

命令返回的布尔值表示是否处理了该动作，不表示文件已经保存。下一章用同样的命令机制[插入自己的内容](/build/extension)，具体方法见 [Editor API](/api/editor)。
