👍 Vue 效率指南,十大幸福小技巧

1,817 阅读3分钟

00-tips.png

作者: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

使用 provideinject 来深度传递数据,无需进行 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 = 类型安全

definePropsdefineEmits 与 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 中获得一流的自动补全和有用的错误检测。

01-error.png

我是大家的 林语冰 👨‍💻,欢迎持续 关注,随时了解海内外前端开发的最新情报。

谢谢的大家点赞、留言和友情转发,我们下期再见~👍

参考文献

[1] VueSchool 官方博客: vueschool.io/articles/vu…

[2] script setup: vuejs.org/api/sfc-scr…

[3] defineExpose: link.juejin.cn/?target=htt…