setup 函数 和 setup 语法糖

很多同学在学 Vue3 的时候会发现,有两种写法:

  • 一种是传统的 setup 函数
  • 一种是更简洁的 <script setup> 语法糖

看起来功能都差不多,到底有没有区别呢? 今天咱们就用大白话给大家解释清楚。


一、两个写法长啥样?

1. setup 函数写法

js 复制代码
<template>
  <div>
    <h1>{{ msg }}</h1>
    <button @click="increase">count: {{ count }}</button>
  </div>
</template>

<script>
import { ref } from 'vue'

export default {
  name: 'FooSetupFn',
  setup(props, { expose }) {
    const msg = 'Hello from setup()'
    const count = ref(0)
    function increase() {
      count.value++
    }

    // 如果需要控制暴露出去的内容
    expose({ msg, count, increase })

    // setup 函数需要手动 return
    return {
      msg,
      count,
      increase,
    }
  }
}
</script>

2. <script setup> 语法糖写法

js 复制代码
<template>
  <div>
    <h1>{{ msg }}</h1>
    <button @click="increase">count: {{ count }}</button>
  </div>
</template>

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

const msg = 'Hello from <script setup>'
const count = ref(0)

function increase() {
  count.value++
}

// 如果要控制暴露,可以用 defineExpose
defineExpose({
  msg,
  count,
  increase
})
</script>

二、运行效果有区别吗?

运行效果其实完全一样:页面都会显示一个标题和一个按钮,点按钮数字会加 1。

所以很多人就会觉得: 这不就是两个写法吗?功能完全一样啊!

但实际上,它们在 底层编译结果默认暴露行为 上是有区别的。


三、内部编译结果区别

Vue 单文件组件(.vue 文件)是不能直接被浏览器运行的,它要经过 编译

我们用 vite-plugin-inspect 插件看编译结果,就能发现区别。

多了expose():


1. setup 函数的编译结果

setup 函数的内容,原封不动放到组件配置对象里:

js 复制代码
const _sfc_main = {
  name: "FooSetupFn",
  setup(props, { expose }) {
    const msg = "Hello from setup()"
    const count = ref(0)
    function increase() {
      count.value++
    }

    expose() // 控制暴露
    return { msg, count, increase }
  }
}

它返回的东西(msg, count, increase),都会被挂到模板里用。


2. <script setup> 的编译结果

<script setup> 会被编译成一个 setup 函数,但是 Vue 会帮你自动 return 里面的变量:

js 复制代码
const _sfc_main = {
  name: "FooScriptSetup",
  setup(__props, { expose }) {
    const msg = "Hello from <script setup>"
    const count = ref(0)
    function increase() {
      count.value++
    }

    // 注意!Vue 自动帮你调用了 expose()
    expose()

    return { msg, count, increase, ref } // 所有顶层变量都会暴露
  }
}

区别就在于:

  • 普通 setup 函数:你自己决定 return 什么。
  • <script setup>:你定义的变量默认都会暴露给模板用。

四、为啥 <script setup> 打印 ref 结果是空的?

当我们用 ref 获取子组件实例,然后打印时:

  • setup 函数组件:实例对象里会看到 msg、count、increase。
  • <script setup> 组件:实例对象是空的,看不到 msg、count、increase。

为啥?

因为 <script setup> 里,Vue 默认加了一行:

js 复制代码
expose()

啥意思呢?意思就是:我不暴露任何东西。 所以你在父组件里拿到子组件实例时,看不到 msg、count 等等。


五、那我想暴露怎么办?

Vue 给我们提供了两个方法:

1. 在 setup 函数里用 expose

js 复制代码
setup(props, { expose }) {
  const msg = 'Hello'
  const count = ref(0)

  expose({ msg, count }) // 只暴露 msg 和 count

  return { msg, count }
}

2. 在 <script setup> 里用 defineExpose

vue 复制代码
<script setup>
import { ref } from 'vue'

const msg = 'Hello'
const count = ref(0)
function increase() {
  count.value++
}

// 只暴露这三个
defineExpose({
  msg,
  count,
  increase
})
</script>

这里的 defineExpose 是一个 宏函数 (编译时才存在),不需要 import,它最后会被编译成 expose()


六、总结

  • <script setup> 就是 setup 函数的语法糖,写法更简洁。

  • setup 函数 → 你自己决定 return 什么。

  • <script setup> → 默认所有变量都能用,但对子组件实例默认不暴露。

  • 想控制暴露的内容:

    • setup 里用 expose()
    • <script setup> 里用 defineExpose()

一句话总结: 👉 平时写组件用 <script setup>,简单省事。 👉 真要做库或者控制暴露,就用 expose / defineExpose

相关推荐
Z兽兽3 小时前
React@18+Vite项目配置env文件
前端·react.js·前端框架
SuniaWang3 小时前
《Spring AI + 大模型全栈实战》学习手册系列 · 专题六:《Vue3 前端开发实战:打造企业级 RAG 问答界面》
java·前端·人工智能·spring boot·后端·spring·架构
A_nanda4 小时前
根据AI提示排查vue前端项目
前端·javascript·vue.js
happymaker06265 小时前
web前端学习日记——DAY05(定位、浮动、视频音频播放)
前端·学习·音视频
~无忧花开~5 小时前
React状态管理完全指南
开发语言·前端·javascript·react.js·前端框架
LegendNoTitle5 小时前
计算机三级等级考试 网络技术 选择题考点详细梳理
服务器·前端·经验分享·笔记·php
@大迁世界5 小时前
1.什么是 ReactJS?
前端·javascript·react.js·前端框架·ecmascript
BJ-Giser6 小时前
Cesium 基于EZ-Tree的植被效果
前端·可视化·cesium
王码码20357 小时前
Flutter for OpenHarmony:Flutter 三方库 algoliasearch 毫秒级云端搜索体验(云原生搜索引擎)
android·前端·git·flutter·搜索引擎·云原生·harmonyos
发现一只大呆瓜7 小时前
深入浅出 AST:解密 Vite、Babel编译的底层“黑盒”
前端·面试·vite