setup() 函数
什么是 setup() 函数?
setup() 函数是 Vue3 组合式 API 的入口点,它在组件实例创建之前执行,用于设置组件的状态、方法和生命周期钩子等。
1. 基本用法
setup() 函数接收两个参数:props 和 context。
示例:基本 setup() 函数
<template>
<div>
<h1>{{ title }}</h1>
<p>计数: {{ count }}</p>
<button @click="increment">增加</button>
</div>
</template>
<script>
export default {
name: 'SetupDemo',
props: {
title: {
type: String,
default: 'Hello Vue3'
}
},
setup(props, context) {
// 组件状态
let count = 0;
// 组件方法
function increment() {
count++;
}
// 返回值将暴露给模板
return {
count,
increment
};
}
}
</script>
2. setup() 的参数
props 参数
props 是一个响应式对象,包含了父组件传递给子组件的所有属性。
示例:使用 props
<script>
export default {
props: {
message: String,
count: Number
},
setup(props) {
console.log(props.message); // 访问 props
// 注意:props 是响应式的,但不能直接解构,否则会失去响应性
// const { message } = props; // 错误:失去响应性
return {};
}
}
</script>
context 参数
context 是一个普通对象,包含了以下属性:
attrs:包含组件的非 props 属性emit:用于触发事件的函数slots:包含组件的插槽expose:用于暴露组件公共方法的函数
示例:使用 context
<script>
export default {
emits: ['update:count'],
setup(props, { attrs, emit, slots, expose }) {
// 使用 emit 触发事件
function updateCount(newCount) {
emit('update:count', newCount);
}
// 暴露公共方法
expose({
updateCount,
reset: () => emit('update:count', 0)
});
return {
updateCount
};
}
}
</script>
3. setup() 与响应式 API
在 setup() 中,需要使用 Vue3 提供的响应式 API 来创建响应式数据。
示例:使用响应式 API
<template>
<div>
<p>计数: {{ count }}</p>
<p>双倍计数: {{ doubleCount }}</p>
<button @click="increment">增加</button>
</div>
</template>
<script>
import { ref, computed } from 'vue';
export default {
setup() {
// 使用 ref 创建响应式数据
const count = ref(0);
// 使用 computed 创建计算属性
const doubleCount = computed(() => count.value * 2);
function increment() {
count.value++;
}
return {
count,
doubleCount,
increment
};
}
}
</script>
4. setup() 与生命周期钩子
在 setup() 中,可以使用 onXXX 形式的生命周期钩子函数。
示例:使用生命周期钩子
<script>
import { onMounted, onUpdated, onUnmounted } from 'vue';
export default {
setup() {
onMounted(() => {
console.log('组件挂载');
});
onUpdated(() => {
console.log('组件更新');
});
onUnmounted(() => {
console.log('组件卸载');
});
return {};
}
}
</script>
5. script setup 语法糖
Vue3 提供了 <script setup> 语法糖,简化了 setup() 函数的写法。
示例:使用 script setup
<template>
<div>
<h1>{{ title }}</h1>
<p>计数: {{ count }}</p>
<button @click="increment">增加</button>
</div>
</template>
<script setup>
// 导入响应式 API
import { ref } from 'vue';
// 定义 props
const props = defineProps({
title: {
type: String,
default: 'Hello Vue3'
}
});
// 定义事件
const emit = defineEmits(['update:count']);
// 创建响应式数据
const count = ref(0);
// 定义方法
function increment() {
count.value++;
emit('update:count', count.value);
}
// 暴露给模板(自动暴露)
</script>
6. setup() 函数的注意事项
- setup() 函数在 beforeCreate 和 created 生命周期钩子之前执行
- setup() 函数中没有 this 上下文
- setup() 函数的返回值会暴露给模板和组件实例
- props 是响应式的,但不能直接解构
- context 不是响应式的,可以安全解构
7. setup() 与选项式 API 的混合使用
在 Vue3 中,可以混合使用组合式 API 和选项式 API,但需要注意一些规则。
示例:混合使用 API
<script>
import { ref } from 'vue';
export default {
data() {
return {
message: 'Hello from options API'
};
},
setup() {
const count = ref(0);
function increment() {
count.value++;
}
return {
count,
increment
};
},
methods: {
greet() {
console.log(this.message);
console.log(this.count); // 可以访问 setup() 中返回的值
}
}
}
</script>
使用场景
- 构建复杂组件,需要更好的代码组织
- 复用逻辑代码,提高代码的可维护性
- 需要更细粒度的响应式控制
- 与 TypeScript 结合使用,获得更好的类型推导
最佳实践
- 优先使用
<script setup>语法糖,简化代码 - 将相关的逻辑组织在一起,提高代码的可读性
- 使用响应式 API 创建组件状态
- 避免在 setup() 中使用 this
- 合理使用生命周期钩子