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

相关推荐
gis开发之家4 小时前
《Vue3 从入门到大神29篇》单元测试与 E2E 测试 —— 保障 Vue3 项目的质量
前端·javascript·vue.js·单元测试·前端框架·vue3
爱勇宝4 小时前
AI 时代,更稀缺的是「提出好问题」还是「判断好答案」?
前端·人工智能·后端
李伟_Li慢慢4 小时前
three.js 中的WebGPU 有几成熟了?
前端·three.js
阿酷tony4 小时前
纯HTML5播放器带倍速、带画质切换的播放器
前端·html·html5
ShiXZ2134 小时前
指令集-NPM 常用指令速查手册
前端·npm·node.js
এ慕ོ冬℘゜4 小时前
前端核心知识体系进阶:从安全机制、网络协议到原生 JS 实战全解析
前端·网络协议·安全
前端H4 小时前
Biome & Rolldown:Rust 工具链接管前端基建
开发语言·前端·rust
forever_world4 小时前
# 💧 从前端视角,彻底搞懂 AI 流式输出 —— 从"接根水管"到 Vue 3 实战
前端·vue.js
灯澜忆梦5 小时前
GO---map函数
开发语言·前端·后端·golang
李剑一5 小时前
uni-app x 实现本地 JSON 文件的导入导出(APP端可用)
android·前端·uni-app