先记住这个答案
组合式 API 没有 onBeforeCreate 和 onCreated,因为 setup 自身就在这些选项式创建阶段附近执行;原来用于初始化状态、建立 computed、同步创建 watch 和调用组合式函数的逻辑可以直接写入 setup。需要真实节点的工作仍放 onMounted,服务端或异步数据也要按相应机制处理。setup 中没有 Options 方法里的组件 this,应该使用 props、ref、inject 和闭包变量。
- 创建阶段初始化直接进入 setup
- 节点操作仍要等待 mounted
- 用闭包与显式参数替换组件 this
setup 本身就是迁移入口
Options API 会先处理 props、inject、methods 与 data 等选项,再进入 created。组合式写法让开发者在 setup 中显式声明这些依赖,不需要再套一层只为“创建完成”而存在的回调。
从旧代码迁移时先按功能拆分:用户偏好读取、请求状态、快捷键订阅各自形成 composable,并把清理与创建放在一起。不要把整个 created 函数原封不动复制成一个巨大的 setup。
用显式输入与返回值组织初始化
下例接收 props,创建本地选择状态和派生标签,并同步建立观察。渲染函数只使用这些闭包变量;卸载清理由组件作用域自动停止 watch,不需要通过 this 访问。
若观察回调创建外部资源,仍要登记该轮清理。自动停止响应式 watch 不等于自动关闭回调里没有接入 Vue 生命周期的第三方连接。
import { computed, defineComponent, h, ref, watch } from 'vue'
const SetupProbe = defineComponent({
props: { prefix: { type: String, default: 'item' } },
setup(props) {
const selected = ref(1)
const label = computed(() => props.prefix + ':' + selected.value)
const changes: string[] = []
watch(label, value => changes.push(value))
return { selected, label, changes }
},
render() {
return h('span', this.label)
}
})状态、派生值和观察在 setup 中同步建立。调用方可通过组件公开返回值改变 selected 并等待刷新,验证 label 和 changes;示例没有节点操作,所以不需要额外等待 onMounted 才初始化。
异步工作不能只靠阶段名称搬运
旧 created 里发请求并不代表组合式代码必须阻塞 setup。可以同步建立 loading、data、error 和清理机制,再启动异步任务;SSR 则要使用框架支持的数据等待方式,避免服务端 HTML 与客户端首态不一致。
如果使用 script setup 顶层 await,需要理解它会生成 async setup 并与 Suspense 协作。普通 Promise 回调则没有相同组件上下文保证,生命周期钩子和 watcher 自动归属仍应在同步初始化部分建立。
容易答错的地方
- 把所有 created 代码放进 onMounted
- 这会把不依赖节点的状态、监听和请求无谓推迟到首屏挂载之后,可能产生空白或错过早期变化。只有真正需要客户端节点的工作才应等待 mounted。
- 在 setup 中继续使用 this
- 组合式 API 的数据通过局部变量、props、context 和返回值组织,不提供 Options 实例 this。强行混用会得到 undefined 或模糊类型,应显式传递依赖并逐步迁移方法。
面试官还会怎么问?
setup 与 beforeCreate 谁先?
在完整 Options 与 Composition 混用顺序中,setup 位于相关创建选项之间;工程迁移更重要的结论是组合式初始化直接写 setup,不需要寻找 onBeforeCreate 或 onCreated。
setup 中能直接发请求吗?
可以启动,但要处理错误、取消、竞态和 SSR 首态。若请求应等待节点或只在浏览器执行,应放到相应客户端时机;若要进入服务端 HTML,则使用框架支持的服务端数据流程。
为什么 watch 要同步创建?
同步 setup 中创建会绑定组件作用域,卸载时自动停止。异步回调稍后才创建的 watch 可能失去这个 owner,必须保存停止句柄并阻止卸载后的迟到创建。
参考资料
示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。