跳转至

Vue3组合式API

<script setup> 是 Vue 3 引入的一种简化的写法,用于使用组合式 API(Composition API)。它能帮助开发者减少样板代码(boilerplate),同时提供更直观、简洁的代码结构。配合 TypeScript 使用时,还能享受静态类型检查和代码提示。

以下是详细介绍 <script lang="ts" setup> 的写法,涵盖 Vue 3 组合式 API 的所有核心功能。

1. 基本介绍

  • 组合式 API:允许通过组合多个独立的逻辑来组织组件代码,避免 Options API 中的同类逻辑分散问题。
  • <script setup>:是 Vue 3.2 引入的语法糖,省去了 setup() 函数和 return 的步骤,代码直接写在 <script setup> 标签中,自动导出给模板使用。

1.1 基本结构

<template>
  <div>{{ message }}</div>
</template>

<script lang="ts" setup>
const message = 'Hello, Vue 3!'
</script>

在这个例子中,message 变量会直接暴露给模板中使用,免去返回它的步骤。

2. 使用 props

<script setup> 中,props 可以直接通过 defineProps 获取。

<template>
  <div>{{ title }}</div>
</template>

<script lang="ts" setup>
interface Props {
  title: string;
}

const props = defineProps<Props>()
</script>
  • defineProps 是一个编译时的 API,专门用来定义组件的 props
  • TypeScript 的类型声明 Props 用于定义 props 的结构。

3. 使用 emit

通过 defineEmits 可以方便地在 <script setup> 中触发自定义事件。

<template>
  <button @click="emitUpdate">Click me</button>
</template>

<script lang="ts" setup>
const emit = defineEmits(['update'])

const emitUpdate = () => {
  emit('update')
}
</script>
  • defineEmits 是用于声明和触发事件的 API。
  • emit('update') 会触发父组件监听的 update 事件。

4. 使用 refreactive

Vue 3 组合式 API 提供了 refreactive 来处理响应式数据。

<template>
  <div>Count: {{ count }}</div>
  <button @click="increment">Increment</button>
</template>

<script lang="ts" setup>
import { ref } from 'vue'

const count = ref(0)

const increment = () => {
  count.value++
}
</script>
  • ref 用于处理基本数据类型的响应式数据,需要通过 .value 访问其值。
  • reactive 适合处理对象或数组的响应式数据。
<script lang="ts" setup>
import { reactive } from 'vue'

const state = reactive({
  count: 0,
  message: 'Hello'
})
</script>

5. 使用 computed

computed 用于定义计算属性,返回基于其他响应式数据的值。

<template>
  <div>Double: {{ doubleCount }}</div>
</template>

<script lang="ts" setup>
import { ref, computed } from 'vue'

const count = ref(2)
const doubleCount = computed(() => count.value * 2)
</script>
  • 计算属性会自动缓存,只有当依赖的响应式数据改变时才会重新计算。

6. 生命周期钩子

<script setup> 中,你可以直接使用 Vue 3 的组合式 API 提供的生命周期钩子。

<template>
  <div>Component Mounted</div>
</template>

<script lang="ts" setup>
import { onMounted, onBeforeUnmount } from 'vue'

onMounted(() => {
  console.log('Component has been mounted')
})

onBeforeUnmount(() => {
  console.log('Component will unmount soon')
})
</script>

常用的生命周期钩子有:

  • onMounted:组件挂载时触发。
  • onBeforeUnmount:组件销毁前触发。
  • 其他的还有 onUpdatedonBeforeUpdate 等。

7. watchwatchEffect

watchwatchEffect 用于监听响应式数据的变化。

  • watch 用于精确监听特定的响应式数据。
<script lang="ts" setup>
import { ref, watch } from 'vue'

const count = ref(0)

watch(count, (newValue, oldValue) => {
  console.log(`Count changed from ${oldValue} to ${newValue}`)
})
</script>
  • watchEffect 是一个立即执行的副作用函数,它会自动依赖所使用的响应式数据。
<script lang="ts" setup>
import { ref, watchEffect } from 'vue'

const count = ref(0)

watchEffect(() => {
  console.log(`Count is now ${count.value}`)
})
</script>

8. defineExpose

通过 defineExpose,可以将内部状态或方法暴露给父组件。

<template>
  <div>Child Component</div>
</template>

<script lang="ts" setup>
const internalFunction = () => {
  console.log('Called from parent')
}

defineExpose({
  internalFunction
})
</script>
  • 父组件可以通过 ref 调用子组件暴露出来的 internalFunction

9. 使用 slotsattrs

可以使用 useSlotsuseAttrs 来获取插槽和 attrs

<template>
  <div>{{ slots.default ? slots.default() : 'No slot content' }}</div>
</template>

<script lang="ts" setup>
const slots = useSlots()
</script>
  • useSlots 用于获取插槽。
  • useAttrs 用于获取除 props 之外传递的其他属性。

10. 类型检查和类型推断

当使用 TypeScript 时,Vue 3 的组合式 API 能很好地推断变量、方法和返回值的类型。在 <script setup> 中,可以直接使用 TypeScript 的类型声明。

<script lang="ts" setup>
import { ref } from 'vue'

const message: string = 'Hello, TypeScript!'
const count = ref<number>(0)
</script>
  • TypeScript 的类型可以显式声明,或者依靠 Vue 的自动类型推断。

11. CSS作用域和样式

<script setup> 与 CSS 一起使用时支持 Vue 组件的样式特性,包括 scoped、CSS 预处理器(如 Sass、Less)等。

<template>
  <div class="styled-box">Styled Box</div>
</template>

<script lang="ts" setup>
// your setup logic here
</script>

<style scoped>
.styled-box {
  background-color: lightblue;
  padding: 10px;
}
</style>

12. 使用模板引用

可以使用 ref 来访问 DOM 元素或组件实例。

<template>
  <input ref="inputRef" />
</template>

<script lang="ts" setup>
import { ref, onMounted } from 'vue'

const inputRef = ref<HTMLInputElement | null>(null)

onMounted(() => {
  if (inputRef.value) {
    inputRef.value.focus()
  }
})
</script>
  • 通过 ref 获取 DOM 元素或组件,并在生命周期钩子中进行操作。

13. 异步操作

<script setup> 中,可以使用 async/await 来处理异步操作。

<template>
  <div>{{ message }}</div>
</template>

<script lang="ts" setup>
import { ref, onMounted } from 'vue'

const message = ref('Loading...')

onMounted(async () => {
  const data = await fetchData()
  message.value = data
})

async function fetchData() {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve('Data loaded!')
    }, 2000)
  })
}
</script>

14. 总结

Vue 3 的 <script setup> 是一种简化组合式 API 的语法糖,提供了更直观、简洁的写法,尤其适合组合式 API 的场景。通过使用 TypeScript,我们可以进一步增强代码的可维护性和类型安全。

主要特点:

  • 不需要显式 setupreturn
  • 所有组合式 API 可以直接在 <script setup> 中使用。
  • 与模板紧密结合,减少样板代码。

评论