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

相关推荐
Bigger11 分钟前
堆了 20 套主题、10+ 组件,用户还是用不出来?我给设计 Skill 加了「自动驾驶」
前端·ai编程·视觉设计
贾天佑忆月 迷失的昵27 分钟前
.NET Web开发技术简单整理
前端·.net
Cobyte1 小时前
Vite & Rollup 插件开发实践
前端·javascript·vue.js
朝阳391 小时前
react19【系列实用教程】实用组件封装
开发语言·前端·javascript
IT_陈寒1 小时前
React的useEffect依赖数组把我坑惨了,原来这样写才靠谱
前端·人工智能·后端
恋猫de小郭1 小时前
Flutter hit,一个可以灵活控制溢出点击的第三方包
android·前端·flutter
古韵1 小时前
小程序上传进度条,还要自己监听 onProgressUpdate 吗?
前端·javascript·uni-app
古韵1 小时前
axios 已经跑得好好的,还要不要上 alova?
前端·javascript·axios
噗噗121 小时前
企业微信侧边栏应用与前端 JS-SDK 的深度整合指南
前端·javascript·企业微信
朝阳391 小时前
react19【实战】配置化路由登录鉴权完整方案
前端·javascript·react.js