Composition API 是 Vue 3 引入的一套新的 API,它提供了一种更灵活的方式来组织组件逻辑。
import { ref, reactive } from 'vue';
// ref - 用于基本类型
const count = ref(0);
console.log(count.value); // 访问值
count.value++; // 修改值
// reactive - 用于对象
const state = reactive({
count: 0,
message: 'Hello'
});
console.log(state.count); // 直接访问,不需要 .value
state.count++; // 直接修改
import { ref, computed } from 'vue';
const count = ref(0);
// 只读计算属性
const doubleCount = computed(() => count.value * 2);
// 可写计算属性
const fullName = computed({
get() {
return `${firstName.value} ${lastName.value}`;
},
set(newValue) {
[firstName.value, lastName.value] = newValue.split(' ');
}
});
import { ref, watch, watchEffect } from 'vue';
const count = ref(0);
// watch - 需要明确指定监听源
watch(count, (newValue, oldValue) => {
console.log(`从 ${oldValue} 变为 ${newValue}`);
});
// 监听多个源
watch([count, another], ([newCount, newAnother]) => {
console.log(newCount, newAnother);
});
// watchEffect - 自动追踪依赖
watchEffect(() => {
console.log(`当前 count: ${count.value}`);
});
// watchPostEffect - DOM 更新后执行
watchPostEffect(() => {
console.log('DOM 已更新');
});
import {
onMounted,
onUpdated,
onUnmounted,
onBeforeMount,
onBeforeUpdate,
onBeforeUnmount
} from 'vue';
export default {
setup() {
onMounted(() => {
console.log('组件已挂载');
});
onUpdated(() => {
console.log('组件已更新');
});
onUnmounted(() => {
console.log('组件已卸载');
});
return {};
}
};
// useMouse.js
import { ref, onMounted, onUnmounted } from 'vue';
export function useMouse() {
const x = ref(0);
const y = ref(0);
function update(event) {
x.value = event.pageX;
y.value = event.pageY;
}
onMounted(() => window.addEventListener('mousemove', update));
onUnmounted(() => window.removeEventListener('mousemove', update));
return { x, y };
}
import { useMouse } from './useMouse';
export default {
setup() {
const { x, y } = useMouse();
return { x, y };
}
};
// 父组件
import { provide, ref } from 'vue'
export default {
setup() {
const theme = ref('light')
provide('theme', theme)
return { theme }
}
}
// 子组件
import { inject } from 'vue'
export default {
setup() {
const theme = inject('theme', 'light') // 默认值 'light'
return { theme }
}
}
import { ref, onMounted } from 'vue';
export default {
setup() {
const inputRef = ref(null);
onMounted(() => {
inputRef.value.focus();
});
return { inputRef };
}
};
<template>
<input ref="inputRef" />
</template>
<script setup>
const props = defineProps({
title: String,
count: {
type: Number,
default: 0
}
});
const emit = defineEmits(['update', 'delete']);
function handleClick() {
emit('update', props.count + 1);
}
</script>
<script setup>
import { ref } from 'vue';
const count = ref(0);
function increment() {
count.value++;
}
// 暴露给父组件
defineExpose({
count,
increment
});
</script>
export default {
setup() {
// 功能 1: 鼠标位置
const { x, y } = useMouse();
// 功能 2: 用户信息
const { user, fetchUser } = useUser();
// 功能 3: 主题切换
const { theme, toggleTheme } = useTheme();
return {
x,
y,
user,
fetchUser,
theme,
toggleTheme
};
}
};
import { ref } from 'vue';
interface User {
id: number;
name: string;
email: string;
}
const user = ref<User | null>(null);
function fetchUser(id: number): Promise<User> {
return fetch(`/api/users/${id}`).then((res) => res.json());
}
// ✓ 推荐: 使用 ref
const count = ref(0);
const user = ref({ name: '张三' });
// ✗ 避免: 解构 reactive
const state = reactive({ count: 0 });
const { count } = state; // 失去响应性
// ✓ 正确: 使用 toRefs
import { toRefs } from 'vue';
const state = reactive({ count: 0 });
const { count } = toRefs(state);
Composition API 提供了更灵活的代码组织方式:
掌握这些概念,你就能写出更优雅、更易维护的 Vue 3 代码!