ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

open-pencil 工具栏响应式分页状态:useToolbarState 源码解析与实战

open-pencil 工具栏响应式分页状态:useToolbarState 源码解析与实战 前端桌面应用AI 应用MCP 服务【免费下载链接】open-pencilAI-native design editor. Open-source Figma alternative.项目地址https://gitcode.com/gh_mirrors/op/open-pencil点击查看免费下载useToolbarState是 open-pencilAI-native 设计编辑器开源 Figma 替代方案Vue SDK 中面向“呈现层”的工具栏状态工具。它不直接读取编辑器工具列表而是专门提供移动端工具栏的分页翻页状态与导航辅助函数如goPrev()、goNext()用于在ToolbarRoot之上搭建自适应工具栏外壳。阅读本文后你将掌握该 composable 的完整返回值语义、分页边界机制、与useToolbar的分工关系并能在自己的工具栏布局中直接复用它。一、useToolbarState 是什么呈现导向的移动端分页状态在 API 进阶参考文档 中useToolbarState()被定义为“返回工具栏相关状态”的 composable当你的自定义界面需要工具栏逻辑可用工具、当前工具、切换动作又不想引入ToolbarRoot组件时可以使用它。结合仓库源码看它的定位更精确useToolbarState是纯呈现层presentation-oriented的工具核心职责是移动端工具栏的分类分页category paging。其实现位于 packages/vue/src/primitives/Toolbar/useToolbarState.tsimport { computed, ref } from vue import type { Tool, EditorToolDef } from open-pencil/core/editor const CATEGORY_COUNT 3 export function useToolbarState() { const mobileCategory ref(0) const slideDirection ref(1) const hasPrev computed(() mobileCategory.value 0) const hasNext computed(() mobileCategory.value CATEGORY_COUNT - 1) function goPrev() { if (!hasPrev.value) return slideDirection.value -1 mobileCategory.value-- } function goNext() { if (!hasNext.value) return slideDirection.value 1 mobileCategory.value } return { mobileCategory, slideDirection, hasPrev, hasNext, isActive: isToolbarToolActive, activeKeyForTool: getToolbarToolSelection, goPrev, goNext } }注释与实现都明确写着“返回响应式工具栏 UI 状态用于移动端分类分页……该 composable 面向呈现层在构建工具栏外壳时补充useToolbar”。也就是说工具列表与激活工具本身来自ToolbarRoot上下文而“当前第几页、能否上翻/下翻、往哪个方向滑动”这类 UI 状态由useToolbarState单独维护。二、返回值全解析八个状态与动作下表汇总了useToolbarState()的完整返回项源码 useToolbarState.ts返回项类型含义mobileCategoryRefnumber当前移动端工具栏分类索引初始为0slideDirectionRefnumber滑动方向-1表示向前翻上一页1表示向后翻下一页初始为1hasPrevComputedRefboolean是否存在上一页mobileCategory 0时为truehasNextComputedRefboolean是否存在下一页mobileCategory CATEGORY_COUNT - 1时为trueisActive(tool, activeTool) boolean判断某个工具定义是否处于激活态含 flyout 子工具activeKeyForTool(tool, activeTool, flyoutSelections?) Tool解析某个工具当前应展示的“选中键”含 flyout 记忆goPrev()() void翻到上一页并把slideDirection置为-1goNext()() void翻到下一页并把slideDirection置为1关键边界逻辑值得注意分类总数固定为 3常量CATEGORY_COUNT 3硬编码在模块顶层useToolbarState.ts。因此hasNext在mobileCategory 2时变为false翻页会停在第 3 页索引 0、1、2。越界保护goPrev()与goNext()在边界处直接return不会产生负索引或越界索引useToolbarState.ts。即便外部按钮状态计算失误也不会破坏分页索引。方向信号slideDirection不是布尔值而是1/-1这是为滑动动画的方向计算准备的——组件可根据该值决定元素从左侧还是右侧进入/退出。三、与 useToolbar、ToolbarRoot 的分工理解useToolbarState必须先厘清工具栏三件套的分工API定位职责ToolbarRoot无样式容器组件ToolbarRoot.vue通过provide提供工具列表、激活工具、flyout 选择记忆与setTool/toggleFlyout/closeFlyout动作useToolbar()上下文读取 composablecontext.ts在ToolbarRoot后代中读取最近上下文在ToolbarRoot之外调用会抛出[open-pencil] useToolbar() called outside ToolbarRoot错误useToolbarState()呈现层状态 composable只负责移动端分页状态与导航动作不依赖上下文可在任何组件中调用useToolbar 的文档也印证了这一点它返回的是最近ToolbarRoot的上下文供需要“工具、激活状态、切换动作”的后代组件使用而useToolbarState提供的是“分页外壳”所需的翻页状态。二者互补useToolbar回答“有哪些工具、当前激活哪个”useToolbarState回答“当前显示哪一页、能否翻页、往哪翻”。关于西班牙语文档中“devuelve la lista de herramientas, la activa y la acción para cambiarla”返回工具列表、激活工具与切换动作的描述从源码结构看这句话更准确地对应useToolbar()的能力useToolbarState的实际实现专注于分页状态。在自行搭建工具栏时推荐按“组件文档 ToolbarRoot 上下文 useToolbar 分页 useToolbarState”的组合理解。四、两个导出辅助函数flyout 激活与选中键解析useToolbarState还向包外导出了两个纯函数useToolbarState.ts它们负责 flyout弹出子工具组场景下的激活判断export function isToolbarToolActive(tool: EditorToolDef, activeTool: Tool): boolean { return tool.key activeTool || (tool.flyout?.includes(activeTool) ?? false) } export function getToolbarToolSelection( tool: EditorToolDef, activeTool: Tool, flyoutSelections?: ReadonlyMapTool, Tool ): Tool { if (tool.flyout?.includes(activeTool)) return activeTool return flyoutSelections?.get(tool.key) ?? tool.key }isToolbarToolActive一个工具定义被视为“激活”要么其key就是当前激活工具要么当前激活工具落在它的flyout子工具列表中。例如FRAME定义的flyout: [FRAME, SECTION]那么激活SECTION时FRAME按钮也应呈现激活态。getToolbarToolSelection解析按钮上应显示的“选中工具”。当激活工具属于某工具的 flyout 时直接返回激活工具本身例如矩形组当前选中了LINE否则回退到flyoutSelections记忆表中的上次选择记忆为空时回退到tool.key自身。flyoutSelections的写入由 ToolbarRoot.vue 完成它watch编辑器激活工具凡落在某工具 flyout 范围内的激活工具都会被记录到flyoutSelectionsMap 中从而记住“这个组上次用的是哪个子工具”。工具定义本身来自核心包 packages/core/src/editor/tool-registry.tsexport interface EditorToolDef { key: Tool label: string shortcut: string flyout?: Tool[] }EDITOR_TOOLS默认注册了SELECT、FRAMEflyout 含SECTION、RECTANGLEflyout 含LINE、ELLIPSE、POLYGON、STAR、PEN、TEXT、HAND六个工具定义tool-registry.ts。ToolbarRoot的toolsprop 默认即取EDITOR_TOOLS可自定义覆盖。五、应用内真实用法桌面/移动工具栏分流open-pencil 主应用把useToolbarState用在了自己的工具栏壳组件中这是最直接的实战范本。在 src/components/Toolbar/Toolbar.vue 中const { mobileCategory, slideDirection, hasPrev, hasNext, goPrev, goNext } useToolbarState()模板中ToolbarRoot以v-slot形式暴露工具上下文再根据视口类型分发到桌面或移动工具栏Toolbar.vueToolbarRoot v-slot{ tools, activeTool, flyoutSelections, actions } DesktopToolbar v-if!isMobile :toolstools :active-toolactiveTool ... / MobileToolbar v-else ... :mobile-categorymobileCategory :slide-directionslideDirection :has-prevhasPrev :has-nexthasNext set-toolactions.setTool prevgoPrev nextgoNext / /ToolbarRoot在移动端工具栏 MobileToolbar.vue 中三个分页分类与CATEGORY_COUNT 3一一对应mobileCategory 0工具页tools渲染各ToolFlyout/ToolbarItemmobileCategory 1编辑页edit渲染editActions动作组mobileCategory 2排列页arrange渲染arrangeActions动作组翻页按钮以hasPrev/hasNext控制禁用与透明度滑动方向通过slideDirection传入AnimatePresence的customprop驱动进入/退出位移MobileToolbar.vueconst slideVariants { initial: (dir: unknown) ({ opacity: 0, x: (dir as number) * 20 }), animate: { opacity: 1, x: 0 }, exit: (dir: unknown) ({ opacity: 0, x: (dir as number) * -20 }) }这就是slideDirection取值1/-1的意义向前翻页时新内容从右侧x: 20滑入退出内容向左x: -20滑出形成方向感明确的翻页动画。六、实战在自定义工具栏中组合使用如果你要自己搭建工具栏外壳无需写任何分页逻辑直接复用useToolbarStatescript setup langts import { useToolbarState } from open-pencil/vue const { mobileCategory, slideDirection, hasPrev, hasNext, goPrev, goNext } useToolbarState() /script template div classtoolbar-shell !-- 上一页按钮边界自动禁用 -- button :disabled!hasPrev clickgoPrev‹/button !-- 当前分类内容可根据 mobileCategory 渲染不同面板 -- div :keymobileCategory :data-directionslideDirection !-- 自定义的工具栏内容 -- /div !-- 下一页按钮 -- button :disabled!hasNext clickgoNext›/button /div /template注意useToolbarState不依赖任何注入上下文因此在ToolbarRoot之外也可以独立使用这正是西班牙语文档强调“无需ToolbarRoot也能拿到工具栏逻辑”的场景。而真正读取工具列表、激活工具与执行setTool则需要嵌套在ToolbarRoot内并使用useToolbar()或像应用那样用ToolbarRoot的v-slot拿到tools、activeTool、actions。二者配合的完整组装方式可参考主应用 Toolbar.vue。从包导出层面useToolbarState、isToolbarToolActive、getToolbarToolSelection均已从open-pencil/vue对外导出packages/vue/src/index.tsToolbarRoot与ToolbarItem组件则在 packages/vue/src/primitives/Toolbar/index.ts 中导出可直接import { useToolbarState, ToolbarRoot, ToolbarItem } from open-pencil/vue。七、相关 API 导航ToolbarRoot 组件文档无样式工具栏容器提供工具与激活工具状态ToolbarItem 组件文档单个工具项提供激活状态与选择动作useToolbar读取最近ToolbarRoot上下文高级 API 索引canvas、图层树、变量等更多底层工具Vue SDK API 总览组件、composables、高级 API 三块导航赞分享前端桌面应用AI 应用MCP 服务【免费下载链接】open-pencilAI-native design editor. Open-source Figma alternative.项目地址https://gitcode.com/gh_mirrors/op/open-pencil点击查看免费下载相关推荐Open-Pencil 响应式选区状态深入解析 useSelectionState() 组合式 APIOpen Pencil 响应式选区状态深入解析 useSelectionState 组合式 API 导读 useSelectionState 是 Open P前端桌面应用AI 应用MCP 服务Open-Pencil 中 useSelectionCapabilities用响应式能力位构建菜单、工具栏与快捷键Open Pencil 中 useSelectionCapabilities用响应式能力位构建菜单、工具栏与快捷键 useSelectionCapabilit前端桌面应用AI 应用MCP 服务HTML 元素与标签完全指南构建网页结构的基础cu/curriculum foundations 课程精讲HTML 元素与标签完全指南构建网页结构的基础cu/curriculum foundations 课程精讲 HTMLHyperText Markup L前端桌面应用AI 应用MCP 服务上一篇终极vcpkg GitHub Action集成指南自动化C项目构建下一篇如何永久保存微信聊天记录这款工具让你的珍贵记忆永不丢失创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表