怎么封装一个可靠的 composable?
先理解原理和示例,再练习完整口述与追问。
回答要点
先定义输入是否响应式、返回值与更新入口、状态是每次调用独立还是共享、清理和 SSR 行为。请求函数还要明确并发、取消、错误与 loading 的归属,别把所有业务揉成一个万能 useRequest。
原理拆解
可靠的 composable 需要明确输入是快照、ref 还是 getter,输出是否可解构且保持响应式,以及副作用何时开始、重新执行与清理。调用一次通常拥有独立状态,不应偷偷使用模块级可变用户数据。请求型能力还要维护 idle/loading/success/error,处理取消、过期响应和重试,调用方才能正确组合。
示例与推演
useUser(idRef) 可监听 ID,开始新请求时清理上一轮控制器,保存请求版本,只让最新版本写 data/error/loading,并在作用域结束时清理。返回 data、loading、error 和 reload,而不是让调用方猜何时请求。若需要 SSR 首屏数据,应结合框架数据获取机制,不应只有客户端 mounted 后才启动。
易错点
不能只把组件代码复制到 useXxx 就算复用。异步创建副作用、返回 reactive 后随意解构、重试不重置错误,都会造成隐藏 bug。
参考回答可直接练习口述
一个 composable 应有明确职责,说明输入是值、ref 还是 getter,返回哪些状态和操作,状态是否每次调用独立。请求类能力还要处理竞争、取消、错误和卸载清理。我会让调用方看到必要依赖,而不是偷偷读取很多全局状态;SSR 中不在模块顶层保存用户数据或访问浏览器对象。
面试官可能继续问追问与完整解答展开收起
追问
传入普通值和 getter 行为不同怎么处理?多个组件同时调用是否共享状态?组件卸载后是否继续写入?
追问回答
传普通值只得到当前输入,传 ref/getter 才有机会追踪后续变化;可按接口设计使用 toValue 等方式规范读取。setup 内每次调用创建的状态通常独立;要共享必须显式放 store 或约定共享服务。卸载时取消任务或失效结果,避免继续修改已失效界面。