Skip to content

Vue 3 无 return 的 Composition API 写法(使用 <script setup> 语法糖)

Vue 3.2+ 引入了 <script setup> 语法糖,可以让你在不使用 return 的情况下更简洁地编写 Composition API 代码。

基础示例

html

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

        <p>Message: {{ message }}</p>
        <input v-model="message">
    </div>
</template>

<script setup>
    import {ref} from 'vue'

    // 声明的变量和函数自动暴露给模板
    const count = ref(0)
    const message = ref('Hello Vue 3')

    function increment() {
        count.value++
    }
</script>

生命周期钩子

html

<script setup>
    import {
        onBeforeMount,
        onMounted,
        onBeforeUpdate,
        onUpdated,
        onBeforeUnmount,
        onUnmounted
    } from 'vue'

    onBeforeMount(() => {
        console.log('beforeMount')
    })

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

    onBeforeUpdate(() => {
        console.log('beforeUpdate')
    })

    onUpdated(() => {
        console.log('updated')
    })

    onBeforeUnmount(() => {
        console.log('beforeUnmount')
    })

    onUnmounted(() => {
        console.log('unmounted')
    })
</script>

计算属性和侦听器

html

<template>
    <div>
        <input v-model="firstName" placeholder="First name">
        <input v-model="lastName" placeholder="Last name">
        <p>Full name: {{ fullName }}</p>

        <p>Question: {{ question }}</p>
        <p>Answer: {{ answer }}</p>
    </div>
</template>

<script setup>
    import {ref, computed, watch} from 'vue'

    const firstName = ref('')
    const lastName = ref('')
    const question = ref('')
    const answer = ref('')

    // 计算属性
    const fullName = computed(() => {
        return `${firstName.value} ${lastName.value}`.trim()
    })

    // 侦听器
    watch(question, async (newQuestion) => {
        if (newQuestion.includes('?')) {
            answer.value = 'Thinking...'
            try {
                const res = await fetch('https://yesno.wtf/api')
                const data = await res.json()
                answer.value = data.answer
            } catch (error) {
                answer.value = 'Error! Could not reach the API. ' + error
            }
        }
    })
</script>

组件通信

父组件

html

<template>
    <ChildComponent
            :title="parentTitle"
            @child-event="handleChildEvent"
    />
</template>

<script setup>
    import {ref} from 'vue'
    import ChildComponent from './ChildComponent.vue'

    const parentTitle = ref('Parent Title')

    function handleChildEvent(payload) {
        console.log('Received from child:', payload)
    }
</script>

子组件

html

<template>
    <div>
        <h2>{{ title }}</h2>
        <button @click="sendToParent">Send to Parent</button>
    </div>
</template>

<script setup>
    // 定义 props
    const props = defineProps({
        title: {
            type: String,
            required: true
        }
    })

    // 定义 emits
    const emit = defineEmits(['child-event'])

    function sendToParent() {
        emit('child-event', {message: 'Hello from child!'})
    }
</script>

组合式函数复用

html

<script setup>
    import {useMouse} from './mouse.js'

    // 使用组合式函数
    const {x, y} = useMouse()
</script>
javascript
// mouse.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}
}

模板引用

html

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

<script setup>
    import {ref, onMounted} from 'vue'

    // 声明模板引用
    const inputRef = ref(null)

    onMounted(() => {
        inputRef.value.focus()
    })
</script>

TypeScript 支持

html

<script setup lang="ts">
    // 带类型的 props
    interface
    Props
    {
        title: string
        count ? : number
    }

    const props = defineProps < Props > ()

    // 带类型的 emits
    const emit = defineEmits < {
    (e
    :
    'update:count', value
    :
    number
    ):
    void
            (e: 'reset')
    :
    void
    }>
    ()

    // 带类型的 ref
    const count = ref < number > (0)
</script>

特点总结

  1. 自动暴露<script setup> 中声明的顶级变量、函数和导入内容自动暴露给模板
  2. 更简洁:无需手动 return 所有需要暴露的内容
  3. 更好的 TypeScript 支持:类型推断更自然
  4. 性能更好:编译时转换,运行时开销更小
  5. 组合式函数更易用:可以像普通函数一样直接使用

注意:<script setup> 是一种编译时语法糖,最终会被编译为标准的 Composition API 代码。

✨ 网站运行时间: 3年11月15天 ❤️ 道阻且长,行则将至 - 微信号: heikedreamer