在 React 项目中优雅实现新用户引导:HagiCode 的 driver.js 实践

张开发
2026/4/6 17:28:28 15 分钟阅读

分享文章

在 React 项目中优雅实现新用户引导:HagiCode 的 driver.js 实践
在 React 项目中优雅实现新用户引导HagiCode 的 driver.js 实践当用户第一次打开你的产品时他们真的知道该从哪里开始吗这篇文章聊聊我们在 HagiCode 项目里用 driver.js 做新用户引导的那些事儿也算是抛砖引玉罢了。背景你有没有遇到过这样的场景新用户注册了你的产品打开页面后一脸茫然东张西望不知道该点哪里、该做什么。作为开发者我们总以为用户会自己探索毕竟人的好奇心是无限的嘛。可现实是——大部分用户会在几分钟内因为找不到入口而悄悄离开就像故事开始得突然结束得也自然。新用户引导是解决这个问题的重要手段只是实现起来也不那么简单。一个好的引导系统需要能够精准定位页面元素并高亮显示支持多步骤引导流程能够记住用户的选择完成/跳过不影响页面性能和正常交互代码结构清晰易于维护在开发 HagiCode 的过程中我们也遇到了同样的挑战。HagiCode 是一个 AI 代码助手项目核心工作流是用户创建提案 → AI 生成计划 → 用户审核 → AI 执行这样一套 OpenSpec 流程。对于第一次接触这个概念的用户来说这套流程是全新的必须有一个好的引导来帮助他们快速上手。毕竟新事物总是需要一点时间的。关于 HagiCode本文分享的方案来自我们在 HagiCode 项目中的实践经验。HagiCode 是一个基于 Claude 的 AI 代码助手通过 OpenSpec 工作流帮助开发者更高效地完成代码任务。你可以在 GitHub 上查看我们的开源代码。为什么选择 driver.js在技术选型阶段我们评估了几个主流的引导库怎么说呢每个都有自己的特点Intro.js功能强大但体积较大样式定制相对复杂Shepherd.jsAPI 设计很好但对于我们的场景来说有点重driver.js轻量、简洁、API 直观且支持 React 生态最终我们选择了 driver.js其实也没什么特别的理由主要基于以下几点考虑轻量级核心库体积小不会显著增加打包体积API 简洁配置项清晰直观上手快灵活性支持自定义定位、样式和交互行为动态导入可以按需加载不影响首屏性能选型这件事其实没有最好的只有最合适的罢了。技术实现核心配置driver.js 的配置非常直观以下是 HagiCode 项目中的核心配置import{driver}fromdriver.js;importdriver.js/dist/driver.css;constnewConversationDriverdriver({allowClose:true,// 允许用户关闭引导animate:true,// 启用动画效果overlayClickBehavior:close,// 点击遮罩层关闭引导disableActiveInteraction:false,// 保持元素可交互showProgress:false,// 不显示进度条我们有自定义进度管理steps:guideSteps// 引导步骤数组});这些配置背后的考虑是allowClose: true- 尊重用户选择不强制完成引导毕竟强扭的瓜不甜disableActiveInteraction: false- 某些步骤需要用户实际操作如输入文字所以不能禁用交互overlayClickBehavior: close- 给用户一个快速的退出方式状态管理引导状态的持久化是关键——我们不希望每次刷新页面都重新引导那样挺烦人的。HagiCode 使用 localStorage 来管理引导状态exporttypeGuideStatepending|dismissed|completed;exportinterfaceUserGuideState{session:GuideState;detailGuides:Recordstring,GuideState;}// 读取状态exportconstgetUserGuideState():UserGuideState{conststatelocalStorage.getItem(userGuideState);returnstate?JSON.parse(state):{session:pending,detailGuides:{}};};// 更新状态exportconstsetUserGuideState(state:UserGuideState){localStorage.setItem(userGuideState,JSON.stringify(state));};我们定义了三种状态pending引导进行中用户还未完成或跳过dismissed用户主动关闭了引导completed用户完成了所有步骤对于提案详情页的引导我们还支持更细粒度的状态追踪通过detailGuides字典因为一个提案可能会经历多个阶段草稿、审核、执行完成每个阶段都需要不同的引导。毕竟事情的状态总是在变化的。目标元素定位driver.js 使用 CSS 选择器来定位目标元素。HagiCode 采用了一个约定使用data-guide自定义属性来标记引导目标conststeps[{element:[data-guidelaunch],popover:{title:开始新对话,description:点击这里创建一个新的对话会话...}}];在组件中这样使用button data-guidelaunchonClick{handleLaunch}新建对话/button这种做法的好处是避免与业务样式类名冲突语义清晰一眼就能看出这个元素与引导相关便于统一管理和维护动态导入优化因为引导功能只在特定场景下才需要比如新用户第一次访问我们采用动态导入来优化初始加载性能constinitNewUserGuideasync(){// 动态导入 driver.jsconst{driver}awaitimport(driver.js);awaitimport(driver.js/dist/driver.css);// 初始化引导constnewConversationDriverdriver({// ...配置});newConversationDriver.drive();};这样 driver.js 及其样式文件只会在需要时才加载不会影响首屏性能。毕竟谁愿意为暂时用不到的东西付出等待的代价呢引导流程设计HagiCode 实现了两条引导路径覆盖了用户的核心使用场景。会话引导10步这条引导帮助用户完成从创建对话到提交第一个完整提案的整个流程launch- 启动引导介绍新建对话按钮compose- 引导用户在输入框中输入请求send- 引导点击发送按钮proposal-launch-readme- 引导创建 README 提案proposal-compose-readme- 引导编辑 README 请求内容proposal-submit-readme- 引导提交 README 提案proposal-launch-agents- 引导创建 AGENTS.md 提案proposal-compose-agents- 引导编辑 AGENTS.md 请求proposal-submit-agents- 引导提交 AGENTS.md 提案proposal-wait- 说明 AI 正在处理请稍候这条引导的设计思路是通过两个实际的提案创建任务README 和 AGENTS.md让用户亲手体验 HagiCode 的核心工作流。毕竟纸上得来终觉浅绝知此事要躬行。下面这几张图对应的就是会话引导里的几个关键节点会话引导的第一步先把用户带到“新建普通会话”的入口上。接着引导用户在输入框里写下第一句请求降低第一次开口的门槛。输入完成后再明确提示用户发送第一条消息让操作路径更连贯。当两个提案都创建完成后引导会回到会话列表让用户知道接下来只需要等待系统继续执行和刷新。提案详情引导3步当用户进入提案详情页时根据提案的当前状态触发对应的引导drafting草稿阶段- 引导用户查看 AI 生成的计划reviewing审核阶段- 引导用户执行计划executionCompleted完成阶段- 引导用户归档计划这条引导的特点是状态驱动——根据提案的实际状态动态决定显示哪个引导步骤。事物总是在变化引导也应该跟着变化才是。下面这张图展示的是提案详情页在“起草阶段”的引导状态在这个阶段引导会把用户注意力聚焦到“生成规划”这个关键动作上避免第一次进入详情页时不知道该先做什么。元素渲染重试机制在 React 应用中引导目标元素可能还没渲染完成比如等待异步数据加载。为了处理这种情况HagiCode 实现了一个重试机制constwaitForElement(selector:string,maxRetries10,interval100){letretries0;returnnewPromiseHTMLElement((resolve,reject){constcheckElement(){constelementdocument.querySelector(selector)asHTMLElement;if(element){resolve(element);}elseif(retriesmaxRetries){retries;setTimeout(checkElement,interval);}else{reject(newError(Element not found:${selector}));}};checkElement();});};在初始化引导前调用这个函数确保目标元素已经存在。有时候多等待一下也是值得的。最佳实践总结基于 HagiCode 的实践经验这里分享几个关键的最佳实践1. 引导应该是可逃离的不要强制用户完成引导。有些用户是探索型的他们更喜欢自己摸索。提供清晰的跳过按钮并记住用户的选择下次不再打扰。毕竟美的事物或人不一定要占有只要她还是美的自己好好看着她的美就好了。2. 引导内容要简洁有力每个引导步骤应该聚焦于单一目标Title简短清晰不超过 10 个字Description直击要点告诉用户这是啥和为啥要用避免长篇大论的说明——用户在引导阶段的注意力是很有限的。话说多了反而没人愿意看。3. 选择器要稳定使用稳定的、不频繁变化的元素标记方式。data-guide自定义属性是一个好选择避免依赖 class 名或 DOM 结构因为这些很容易在重构中变化。代码总是在变化的但有些东西应该尽量保持稳定。4. 测试你的引导HagiCode 为引导功能编写了完整的测试用例describe(NewUserConversationGuide,(){it(应该正确初始化引导状态,(){conststategetUserGuideState();expect(state.session).toBe(pending);});it(应该正确更新引导状态,(){setUserGuideState({session:completed,detailGuides:{}});conststategetUserGuideState();expect(state.session).toBe(completed);});});测试可以确保在重构代码时不会不小心破坏引导功能。毕竟谁也不希望改点代码就把之前的功能搞坏了。5. 性能优化使用动态导入延迟加载引导库避免在用户已经完成引导后仍然初始化引导逻辑考虑引导动画的性能影响低端设备上可以关闭动画性能这东西就像生活一样该省的地方还是要省的。总结新用户引导是提升产品用户体验的重要环节。在 HagiCode 项目中我们使用 driver.js 构建了一套完整的引导系统覆盖了从会话创建到提案执行的整个工作流。通过本文的分享我们希望传达的核心观点是技术选型要匹配需求driver.js 不是最强的但对我们来说是最合适的状态管理很关键用 localStorage 持久化引导状态避免重复打扰用户引导设计要聚焦每个步骤解决一个问题不要贪多代码结构要清晰分离引导配置、状态管理和 UI 逻辑便于维护如果你正在为自己的项目添加新用户引导功能希望本文的实践经验能对你有所帮助。其实技术这东西也没什么神秘的多尝试多总结慢慢就好了…参考资料driver.js 官方文档HagiCode 项目源码HagiCode 官网OpenSpec 工作流说明原文与版权说明感谢您的阅读,如果您觉得本文有用,欢迎点赞、收藏和分享支持。本内容采用人工智能辅助协作,最终内容由作者审核并确认。本文作者: newbe36524原文链接: https://docs.hagicode.com/go?platformcsdntarget%2Fblog%2F2026-04-01-new-user-guide-with-driverjs%2F版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!

更多文章