Vue 3 :详解setup 函数
什么是 setup 函数?
setup 是 Vue 3 组合式 API 的核心和入口。可以把它理解为组件的"控制中心"——所有组件的逻辑都在这里组织和执行。
执行时机与特点
export default {setup() {console.log('setup 执行了')},beforeCreate() {console.log('beforeCreate 执行了')},created() {console.log('created 执行了')}
}
执行顺序: setup → beforeCreate → created
重要特性: 在 setup 中无法访问 this,因为此时组件实例还没有创建完成。
setup 的参数解析
setup 函数接收两个重要的参数:
1. props - 接收父组件传递的数据
export default {props: ['title', 'content'],setup(props) {// 访问 propsconsole.log(props.title) // 获取 titleconsole.log(props.content) // 获取 content// props 是响应式的,可以使用 watch 监听watch(() => props.title, (newVal, oldVal) => {console.log(`title 从 ${oldVal} 变为 ${newVal}`)})return {}}
}
2. context - 组件的上下文信息
context 是一个普通对象,包含三个常用属性:
export default {setup(props, context) {// 1. attrs - 获取未在 props 中声明的属性console.log(context.attrs.class) // 获取 class 属性console.log(context.attrs.style) // 获取 style 属性// 2. slots - 访问插槽内容console.log(context.slots.default) // 默认插槽console.log(context.slots.header) // 具名插槽// 3. emit - 触发自定义事件const handleClick = () => {context.emit('update', '新数据')}return {handleClick}}
}
更常用的解构写法:
setup(props, { attrs, slots, emit }) {// 直接使用 attrs、slots、emit
}
setup 的返回值
setup 必须返回一个对象,这个对象中的属性和方法可以在模板中直接使用:
import { ref, computed } from 'vue'export default {setup() {// 响应式数据const count = ref(0)const name = ref('张三')// 计算属性const doubleCount = computed(() => count.value * 2)// 方法const increment = () => {count.value++}const reset = () => {count.value = 0name.value = '张三'}// 返回给模板使用return {count,name,doubleCount,increment,reset}}
}
在模板中直接使用:
<template><div><p>{{ name }}的计数器:{{ count }}</p><p>双倍:{{ doubleCount }}</p><button @click="increment">+1</button><button @click="reset">重置</button></div>
</template>
实际开发示例
用户管理组件
<template><div><input v-model="userForm.name" placeholder="姓名"><input v-model="userForm.age" placeholder="年龄"><button @click="addUser" :disabled="!isFormValid">添加用户</button><ul><li v-for="user in users" :key="user.id">{{ user.name }} - {{ user.age }}岁</li></ul></div>
</template><script>
import { ref, reactive, computed } from 'vue'export default {setup() {// 响应式数据const users = ref([])const userForm = reactive({name: '',age: ''})// 计算属性const isFormValid = computed(() => {return userForm.name.trim() && userForm.age})// 方法const addUser = () => {if (!isFormValid.value) returnusers.value.push({id: Date.now(),name: userForm.name,age: userForm.age})// 重置表单userForm.name = ''userForm.age = ''}return {users,userForm,isFormValid,addUser}}
}
</script>
结合生命周期钩子
在 setup 中使用生命周期函数:
import { onMounted, onUpdated, onUnmounted } from 'vue'export default {setup() {const data = ref(null)onMounted(() => {console.log('组件挂载完成')// 在这里可以执行初始化操作,比如请求数据})onUpdated(() => {console.log('组件更新了')})onUnmounted(() => {console.log('组件卸载了')// 在这里可以执行清理操作})return {data}}
}
<script setup> 语法糖
Vue 3.2 引入了更简洁的 <script setup> 语法:
<template><div><p>{{ count }}</p><button @click="increment">+1</button></div>
</template><script setup>
import { ref } from 'vue'// 变量和函数自动暴露给模板
const count = ref(0)
const increment = () => {count.value++
}// 定义 props 和 emits
defineProps({title: String
})defineEmits(['update'])
</script>
总结
setup 函数是 Vue 3 组合式 API 的基石,它:
- 提供了统一的逻辑组织方式
- 接收
props和context参数 - 通过返回值暴露模板需要的内容
