作者:
Daniel Kelly
译者:
林语冰
资源:VueSchool 官方博客[1]
免责声明:活人翻译,略有删改,仅供粉丝参考!
01. 组合式 API + script setup
与选项式 API 相比,组合式 API 具有多个优点,包括:
- 通过关注逻辑更好地组织代码
- 更容易复用状态逻辑
- 改进了类型安全性
script setup[2] 语法糖提供了最直观精简的方式来使用组合式 API:
<script setup>
import { ref, computed } from 'vue'
const count = ref(0)
function increment() {
count.value++
}
</script>
<template>
<button @click="increment">count 的值:{{ count }}</button>
</template>
这种语法减少了样板代码,并使你的组件更具可读性。
02. toRefs
响应式解构
当你需要解构响应式对象时,请使用 toRefs
来保持响应性:
<script setup>
import { toRefs } from 'vue'
const props = defineProps<{
title: string
count?: number
}>()
const { title, count } = toRefs(props)
console.log(title.value)
// props 变化时会响应式更新
</script>
03. 组合式函数复用
将可复用的逻辑提取到组合式函数中:
// useCounter.js
import { ref } from 'vue'
export function useCounter(initial = 0) {
const count = ref(initial)
function increment() {
count.value++
}
return { count, increment }
}
<script setup>
// Component.vue
import { useCounter } from './useCounter'
const { count, increment } = useCounter(10)
</script>
这可以促进代码复用并保持组件干净,这也是我优先推荐组合式 API 而不是选项式 API 的首要原因之一。
如果你使用组合式 API 编写组件,那么抽象出这些组合式函数的时机就更明显了。
04. watchEffect
watchEffect
立即运行函数,同时被动地跟踪其依赖:
<script setup>
import { ref, watchEffect } from 'vue'
const count = ref(0)
const message = ref('')
watchEffect(() => {
message.value = `count 的值为:${count.value}`
})
</script>
这对于依赖响应式状态的副作用非常有用。
05. provide + inject
使用 provide
和 inject
来深度传递数据,无需进行 props
逐层透传:
<!-- Parent.vue -->
<script setup>
import { provide, ref } from 'vue'
const theme = ref('light')
provide('theme', theme)
</script>
<!-- DeepChild.vue -->
<script setup>
import { inject } from 'vue'
const theme = inject('theme', 'light')
// 这里的 light 是默认值
</script>
这简化了将数据传递到深层嵌套组件的过程,并且对于许多实际用例而言非常方便。
06. shallowRef 优化
当处理不需要深度响应性的大型对象时,请使用shallowRef
:
<script setup>
import { shallowRef } from 'vue'
const largeObject = shallowRef({ /* 海量属性 */ })
function updateObject() {
largeObject.value = { /* 大型对象 */ }
}
</script>
这可以显著提高大型且频繁更新的对象的性能。
07. defineExpose 暴露接口
通过 <script setup>
,使用 defineExpose[3] 显式控制向父组件暴露的内容:
<!-- AppModal.vue -->
<script setup>
import { ref } from 'vue'
const isOpen = ref(false)
function open() {
isOpen.value = true
}
function close() {
isOpen.value = true
}
defineExpose({ open, close })
</script>
<!-- ParentComponent.vue -->
<script setup>
const modal = ref();
</script>
<template>
<button @click="modal.open()">打开模态框</button>
<AppModal ref="modal">
</template>
这使你可以对组件的公共 API 进行细粒度的控制。
08. effectScope 分组清理
使用 effectScope
对多个副作用进行分组和清理:
import { effectScope, onScopeDispose } from 'vue'
const scope = effectScope()
scope.run(() => {
// 这里创建的所有 effect 都会自动处置
const data = ref(null)
watchEffect(() => {/* ... */})
watch(data, () => {/* ... */})
})
onScopeDispose(() => {
scope.stop()
// 停用 scope 中的所有 effect
})
这对于创建设置和清除多个 effect 的组合式函数特别有用。
通过应用这些 Vue 3 专属技巧,你可以创建更高效、可维护,且功能强大的 Vue 应用程序。
09. SFC 双脚本标记
Vue 单文件组件中可以有 2 个 <script>
标记:一个具有 setup
属性,另一个没有。由于诸多原因,有时这可能会有所帮助。
其中原因之一是导出与组件紧密相关,但可能在其他地方有用的类型或数据。
<!-- UserProfileComponent -->
<script lang="ts">
export interface UserProfile{
username: string,
// 其他内容...
}
</script>
<script setup lang="ts">
defineProps<UserProfile>()
</script>
另一种方法是导出紧密耦合组件的 provide/inject key。
10. defineProps + defineEmits = 类型安全
将 defineProps
和 defineEmits
与 TS 结合使用,实现更棒的类型推断:
<script setup lang="ts">
const props = defineProps<{
title: string
count?: number
}>()
const emit = defineEmits<{
change: [id: number];
update: [value: string];
}>();
// 类型安全的使用
emit('change', 1)
</script>
这为组件的外部 API 提供了类型安全,这意味着组件用户可以在其 IDE 中获得一流的自动补全和有用的错误检测。
我是大家的 林语冰
👨💻,欢迎持续 关注,随时了解海内外前端开发的最新情报。
谢谢的大家点赞、留言和友情转发,我们下期再见~👍
参考文献
[1] VueSchool 官方博客: vueschool.io/articles/vu…
[2] script setup: vuejs.org/api/sfc-scr…
[3] defineExpose: link.juejin.cn/?target=htt…