在 Vue3 中,直接写在 <script setup>...</script>
中的代码运行时机可以分为以下几个关键阶段:
一、执行顺序层级
二、具体运行阶段
1. 组件实例初始化前
- 执行时机:在 Vue 实例化过程中,早于
beforeCreate
生命周期钩子 - 典型行为:
<script setup> // 以下代码会先于 beforeCreate 执行 import { ref } from 'vue' const count = ref(0) // 响应式变量初始化 console.log('ScriptSetup 执行') // 会在此阶段输出 </script>
2. 响应式系统构建
- 依赖收集:所有在
<script setup>
中声明的ref
/reactive
变量会被立即初始化 - 示例验证:
<script setup> const message = ref('Hello') console.log(message.value) // 输出 "Hello" </script>
3. 生命周期钩子对比
代码位置 | 执行时机 | 示例 |
---|---|---|
<script setup> | beforeCreate 之前 | 初始化响应式变量、导入模块 |
setup() 函数 | beforeCreate 之前 | (等同于 <script setup> ) |
onMounted 钩子 | 组件挂载完成后 | 访问 DOM 元素 |
created 钩子 | beforeCreate 之后 | 不能访问 DOM |
三、异步操作的特殊处理
1. 异步代码执行时机
<script setup>
// 以下异步代码会立即执行(在实例化前)
const fetchData = async () => {const res = await fetch('/api/data')data.value = await res.json()
}
fetchData() // 立即发起请求
</script>
2. 与生命周期的关系
- 请求会在
beforeCreate
前发起,但响应处理会在组件挂载后完成 - 典型场景:
<script setup> import { ref, onMounted } from 'vue'const data = ref(null)// 立即执行的异步请求 fetchData().then(res => {data.value = res // 在 mounted 钩子前可能已赋值 })onMounted(() => {console.log(data.value) // 可能已有值(取决于请求速度) }) </script>
四、与选项式 API 的对比
特性 | <script setup> | 选项式 API (setup() 函数) |
---|---|---|
执行时机 | beforeCreate 前 | beforeCreate 前 |
响应式声明 | ref /reactive 直接声明 | 需要返回对象 |
代码组织 | 更简洁,无 this 上下文 | 需要 this 访问实例 |
编译优化 | Tree-shaking 友好 | 需要手动优化 |
五、关键注意事项
1. 不要访问 DOM
<script setup>
// ❌ 错误:此时 DOM 尚未创建
const element = document.getElementById('app')
</script>
2. 异步数据获取
<script setup>
// ✅ 正确:在 setup 阶段发起请求
const data = ref(null)fetch('/api/data').then(res => {data.value = res.json()
})
</script>
3. 响应式变量初始化
<script setup>
// ✅ 正确:响应式变量在实例化前初始化
const count = ref(0)
</script>
六、底层原理
-
编译阶段:
- Vue 编译器将
<script setup>
转换为setup()
函数 - 所有顶层代码被提升到
setup()
最顶部
- Vue 编译器将
-
运行时阶段:
- 在组件实例化流程中,先执行
<script setup>
代码 - 再依次触发
beforeCreate
→created
→beforeMount
等生命周期
- 在组件实例化流程中,先执行
总结
- 运行时机:
<script setup>
中的代码在 组件实例化前 执行(早于beforeCreate
) - 核心特性:
- 响应式变量立即初始化
- 顶级代码立即执行
- 无法访问 DOM 元素
- 最佳实践:
- 用于初始化数据、导入模块、注册组合函数
- 异步操作需注意执行顺序
- 避免在此阶段直接操作 DOM