Appearance
Vue 3 API 指南
本文档按照 API 重要程度由高到低排序,详细介绍 Vue 3 中的核心 API,包括其作用、区别和使用场景。
一、核心 Composition API
1. setup()
作用:Composition API 的入口函数,用于在组件中使用 Composition API。
使用场景:
- 替代 Options API 中的 data、methods、computed 等选项
- 组织相关逻辑代码,提高代码可读性和可维护性
- 实现逻辑复用
示例:
vue
<template>
<div>{{ count }}</div>
<button @click="increment">Increment</button>
</template>
<script>
import { ref } from 'vue'
export default {
setup() {
const count = ref(0)
const increment = () => {
count.value++
}
return { count, increment }
}
}
</script>2. ref()
作用:创建响应式的引用类型数据。
区别:
- 与 reactive() 相比,ref() 可以处理基本类型数据
- ref() 创建的数据需要通过 .value 访问和修改
- 在模板中使用时,Vue 会自动解包,无需 .value
使用场景:
- 管理基本类型的响应式数据
- 在组合函数中返回响应式数据
- 作为 props 或 emits 的默认值
示例:
javascript
import { ref } from 'vue'
const count = ref(0)
console.log(count.value) // 0
count.value++
console.log(count.value) // 13. reactive()
作用:创建响应式的对象类型数据。
区别:
- 只能处理对象类型数据
- 直接访问和修改属性,无需 .value
- 解构后会失去响应性
使用场景:
- 管理复杂的对象类型数据
- 当需要同时响应多个相关属性时
示例:
javascript
import { reactive } from 'vue'
const state = reactive({
count: 0,
name: 'Vue 3'
})
console.log(state.count) // 0
state.count++
console.log(state.count) // 14. computed()
作用:创建计算属性,根据依赖自动缓存结果。
使用场景:
- 基于响应式数据计算派生值
- 避免在模板中进行复杂计算
- 提高性能,避免重复计算
示例:
javascript
import { ref, computed } from 'vue'
const count = ref(0)
const doubleCount = computed(() => count.value * 2)
console.log(doubleCount.value) // 0
count.value++
console.log(doubleCount.value) // 25. watch()
作用:监听响应式数据的变化并执行副作用。
区别:
- 与 watchEffect() 相比,watch() 可以:
- 明确指定要监听的数据源
- 获取变化前后的值
- 控制触发时机(immediate、deep)
使用场景:
- 当需要在数据变化时执行异步操作
- 当需要基于变化前后的值进行逻辑处理
- 当需要深度监听对象或数组的变化
示例:
javascript
import { ref, watch } from 'vue'
const count = ref(0)
watch(count, (newValue, oldValue) => {
console.log(`Count changed from ${oldValue} to ${newValue}`)
})
count.value++ // 输出: Count changed from 0 to 16. watchEffect()
作用:自动追踪响应式依赖并执行副作用。
区别:
- 与 watch() 相比,watchEffect() 会:
- 自动追踪所有依赖
- 立即执行一次
- 无法获取变化前后的值
使用场景:
- 当需要根据多个响应式数据的变化执行副作用
- 当副作用的依赖关系比较复杂
- 当不需要获取变化前后的值
示例:
javascript
import { ref, watchEffect } from 'vue'
const count = ref(0)
const name = ref('Vue')
watchEffect(() => {
console.log(`Count: ${count.value}, Name: ${name.value}`)
})
count.value++ // 输出: Count: 1, Name: Vue
name.value = 'Vue 3' // 输出: Count: 1, Name: Vue 37. onMounted() / onUpdated() / onUnmounted()
作用:生命周期钩子函数,用于在组件不同阶段执行逻辑。
使用场景:
- onMounted:组件挂载后执行,如初始化数据、绑定事件等
- onUpdated:组件更新后执行,如 DOM 操作、第三方库更新等
- onUnmounted:组件卸载前执行,如清理定时器、取消事件监听等
示例:
javascript
import { onMounted, onUnmounted } from 'vue'
export default {
setup() {
let timer
onMounted(() => {
timer = setInterval(() => {
console.log('Tick')
}, 1000)
})
onUnmounted(() => {
clearInterval(timer)
})
}
}二、响应式系统 API
1. readonly()
作用:创建只读的响应式对象。
使用场景:
- 保护数据不被修改
- 传递数据给子组件时防止意外修改
- 实现不可变数据模式
示例:
javascript
import { reactive, readonly } from 'vue'
const state = reactive({ count: 0 })
const readOnlyState = readonly(state)
readOnlyState.count++ // 警告:无法修改只读对象2. shallowRef() / shallowReactive()
作用:创建浅响应式数据,只响应顶层属性的变化。
使用场景:
- 当不需要深度响应式时,提高性能
- 当处理大型对象或数组时
- 当对象的深层结构不需要响应式时
示例:
javascript
import { shallowRef, shallowReactive } from 'vue'
const shallowObj = shallowReactive({
deep: { nested: 1 }
})
shallowObj.deep.nested = 2 // 不会触发响应式更新3. toRef() / toRefs()
作用:将响应式对象的属性转换为 ref。
使用场景:
- 当需要解构响应式对象的属性时保持响应性
- 当需要将对象属性作为 ref 传递给其他函数时
示例:
javascript
import { reactive, toRef, toRefs } from 'vue'
const state = reactive({ count: 0, name: 'Vue' })
const countRef = toRef(state, 'count')
const { name } = toRefs(state)
countRef.value++ // 会触发响应式更新
name.value = 'Vue 3' // 会触发响应式更新4. isRef() / isReactive() / isReadonly()
作用:判断数据的响应式类型。
使用场景:
- 在组合函数中检查参数类型
- 实现通用逻辑时进行类型判断
- 调试时检查响应式状态
示例:
javascript
import { ref, reactive, readonly, isRef, isReactive, isReadonly } from 'vue'
const count = ref(0)
const state = reactive({ count: 0 })
const readOnlyState = readonly(state)
console.log(isRef(count)) // true
console.log(isReactive(state)) // true
console.log(isReadonly(readOnlyState)) // true三、组件 API
1. defineComponent()
作用:定义 Vue 组件,提供类型推导支持。
使用场景:
- 在 TypeScript 项目中定义组件
- 获得更好的类型提示和代码补全
示例:
typescript
import { defineComponent } from 'vue'
export default defineComponent({
props: {
message: String
},
setup(props) {
return {
// 这里可以获得 props 的类型提示
}
}
})2. defineProps() / defineEmits()
作用:在 <script setup> 中定义组件的 props 和 emits。
使用场景:
- 在
<script setup>语法中使用 - 获得更好的类型推导
- 简化组件定义
示例:
vue
<script setup>
import { defineProps, defineEmits } from 'vue'
const props = defineProps({
message: String
})
const emit = defineEmits(['update:message'])
function updateMessage(newMessage) {
emit('update:message', newMessage)
}
</script>3. useSlots() / useAttrs()
作用:在 Composition API 中访问组件的 slots 和 attrs。
使用场景:
- 当需要在 setup() 中操作 slots 时
- 当需要在 setup() 中访问非 props 的属性时
示例:
javascript
import { useSlots, useAttrs } from 'vue'
export default {
setup() {
const slots = useSlots()
const attrs = useAttrs()
console.log(slots.default)
console.log(attrs.class)
return {}
}
}四、工具 API
1. nextTick()
作用:在下次 DOM 更新后执行回调函数。
使用场景:
- 当需要在 DOM 更新后操作元素
- 当需要获取更新后的 DOM 状态
- 当需要在数据变化后执行 DOM 相关的操作
示例:
javascript
import { ref, nextTick } from 'vue'
const count = ref(0)
async function increment() {
count.value++
// DOM 还未更新
await nextTick()
// DOM 已更新,可以操作元素
console.log(document.getElementById('count').textContent)
}2. provide() / inject()
作用:实现组件间的依赖注入。
使用场景:
- 当需要在组件树中传递数据,而不想通过 props 逐层传递
- 当需要在深层嵌套的组件中共享状态
- 当需要实现插件或库的功能
示例:
javascript
// 父组件
import { provide } from 'vue'
export default {
setup() {
provide('theme', 'dark')
}
}
// 子组件
import { inject } from 'vue'
export default {
setup() {
const theme = inject('theme', 'light') // 第二个参数是默认值
return { theme }
}
}3. h()
作用:创建 VNode(虚拟 DOM 节点)。
使用场景:
- 当需要动态创建组件时
- 当需要在渲染函数中使用
- 当需要实现高阶组件时
示例:
javascript
import { h } from 'vue'
// 创建一个 div 元素
const vnode = h('div', { class: 'container' }, [
h('h1', 'Hello Vue 3'),
h('p', 'Welcome to the Vue 3 world')
])4. resolveComponent() / resolveDirective()
作用:解析组件或指令。
使用场景:
- 在渲染函数中动态使用组件
- 在运行时解析组件名称
示例:
javascript
import { h, resolveComponent } from 'vue'
export default {
setup() {
const MyComponent = resolveComponent('MyComponent')
return () => h(MyComponent)
}
}五、其他 API
1. markRaw()
作用:标记一个对象,使其永远不会被转换为响应式对象。
使用场景:
- 当需要处理大型第三方库对象时
- 当需要提高性能,避免不必要的响应式转换
- 当对象不需要响应式时
示例:
javascript
import { markRaw, reactive } from 'vue'
const rawObj = { count: 0 }
const markedObj = markRaw(rawObj)
const reactiveObj = reactive(markedObj)
console.log(reactiveObj === markedObj) // true,说明没有被转换为响应式2. customRef()
作用:创建自定义的 ref 类型。
使用场景:
- 当需要自定义响应式行为时
- 当需要实现防抖或节流等功能时
- 当需要控制依赖追踪和触发更新的时机时
示例:
javascript
import { customRef } from 'vue'
function useDebouncedRef(value, delay = 300) {
let timeout
return customRef((track, trigger) => {
return {
get() {
track()
return value
},
set(newValue) {
clearTimeout(timeout)
timeout = setTimeout(() => {
value = newValue
trigger()
}, delay)
}
}
})
}
// 使用
const searchQuery = useDebouncedRef('')3. effectScope()
作用:创建一个 effect 作用域,可以手动控制其中的响应式副作用的生命周期。
使用场景:
- 当需要在组件之外使用响应式系统时
- 当需要手动管理响应式副作用的清理
- 当需要创建可复用的响应式逻辑时
示例:
javascript
import { effectScope, ref, watch } from 'vue'
const scope = effectScope()
scope.run(() => {
const count = ref(0)
watch(count, newValue => {
console.log(`Count: ${newValue}`)
})
count.value++ // 输出: Count: 1
})
// 清理所有副作用
scope.stop()
// 之后的修改不会触发 watch
count.value++ // 不会输出总结
Vue 3 的 API 设计更加灵活和强大,特别是 Composition API 的引入,使得代码组织更加清晰,逻辑复用更加方便。根据不同的使用场景,选择合适的 API 可以提高开发效率和代码质量。
重要程度排序
- 核心 Composition API:setup(), ref(), reactive(), computed(), watch(), watchEffect(), 生命周期钩子
- 响应式系统 API:readonly(), shallowRef(), shallowReactive(), toRef(), toRefs(), 响应式判断函数
- 组件 API:defineComponent(), defineProps(), defineEmits(), useSlots(), useAttrs()
- 工具 API:nextTick(), provide(), inject(), h()
- 其他 API:markRaw(), customRef(), effectScope()
通过合理使用这些 API,可以构建出更加健壮、可维护的 Vue 3 应用。