Vue3:setup详解

Vue3:setup详解

  • [一、setup 是什么?](#一、setup 是什么?)
  • 二、基本语法
  • [三、setup 的两个参数](#三、setup 的两个参数)
    • [3.1 props --- 父组件传参](#3.1 props — 父组件传参)
    • [3.2 context --- 上下文](#3.2 context — 上下文)
  • [四、setup 能做什么?](#四、setup 能做什么?)
    • [4.1 声明响应式数据](#4.1 声明响应式数据)
    • [4.2 计算属性 computed](#4.2 计算属性 computed)
    • [4.3 侦听器 watch](#4.3 侦听器 watch)
    • [4.4 生命周期钩子](#4.4 生命周期钩子)
    • [4.5 方法定义](#4.5 方法定义)
  • [五、逻辑复用(组合函数 useXxx)](#五、逻辑复用(组合函数 useXxx))
  • [六、setup 的注意事项](#六、setup 的注意事项)
  • 七、完整示例

一、setup 是什么?

setup 是 Vue 3 引入的组合式 API(Composition API)核心入口,是一个在组件实例创建之前执行的函数,用于替代 Vue 2 中的 beforeCreatecreated 钩子。

复制代码
执行顺序:
setup() → beforeCreate() → created() → ...其他生命周期

⚠️ 关键点:setup 中 thisundefined,不能用 this 访问组件实例!


二、基本语法

写法一:选项式写法(传统)

javascript 复制代码
<template>
  <div>
    <p>{{ count }}</p>
    <button @click="increment">+1</button>
  </div>
</template>

<script>
import { ref } from 'vue'

export default {
  // ✅ Vue3 新增选项
  setup() {
    const count = ref(0)
    const increment = () => { count.value++ }

    // 🎯 返回值暴露给模板
    return { count, increment }
  }
}
</script>

写法二:<script setup> 语法糖(推荐 ⭐⭐⭐⭐⭐)

javascript 复制代码
<template>
  <div>
    <p>{{ count }}</p>
    <button @click="increment">+1</button>
  </div>
</template>

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

// ✅ 不需要 return,自动暴露给模板
const count = ref(0)
const increment = () => { count.value++ }
</script>

💡 推荐用 <script setup>,更简洁,不用写 return


三、setup 的两个参数

js 复制代码
setup(props, context) {
  // props    → 父组件传来的数据(响应式)
  // context  → 上下文对象 { attrs, slots, emit }
}

3.1 props --- 父组件传参

js 复制代码
export default {
  props: {
    title: String,
    count: { type: Number, default: 0 }
  },
  setup(props) {
    console.log(props.title)   // ✅ 直接访问
    console.log(props.count)

    // ⚠️ 不要解构!会丢失响应性
    // const { title } = props  ❌

    // ✅ 要解构用 toRefs
    import { toRefs } from 'vue'
    const { title } = toRefs(props)  // title.value
  }
}

3.2 context --- 上下文

js 复制代码
setup(props, { attrs, slots, emit }) {
  // attrs  → 未在 props 中声明的属性
  // slots → 插槽内容
  // emit  → 触发父组件事件

  const sendEvent = () => {
    emit('custom-event', 'hello')  // 通知父组件
  }

  return { sendEvent }
}

四、setup 能做什么?

4.1 声明响应式数据

API 用途 示例
ref() 单个值(基本类型/对象) const count = ref(0)
reactive() 对象/数组 const state = reactive({ name: 'Tom' })
js 复制代码
import { ref, reactive } from 'vue'

setup() {
  // ref:JS 中用 .value,模板中自动解包不用 .value
  const count = ref(0)

  // reactive:直接访问属性
  const user = reactive({
    name: '张三',
    age: 20
  })

  return { count, user }
}

4.2 计算属性 computed

js 复制代码
import { ref, computed } from 'vue'

setup() {
  const count = ref(0)
  const double = computed(() => count.value * 2)

  return { count, double }
}

4.3 侦听器 watch

js 复制代码
import { ref, watch } from 'vue'

setup() {
  const count = ref(0)

  watch(count, (newVal, oldVal) => {
    console.log(`从 ${oldVal} 变为 ${newVal}`)
  })

  return { count }
}

4.4 生命周期钩子

js 复制代码
import {
  onMounted,
  onUpdated,
  onUnmounted,
  onBeforeMount,
  onBeforeUpdate
} from 'vue'

setup() {
  onMounted(() => {
    console.log('组件挂载完成')
  })

  onUnmounted(() => {
    console.log('组件销毁')
    // 清除定时器等操作
  })

  return {}
}

4.5 方法定义

js 复制代码
setup() {
  const count = ref(0)

  // 普通函数
  const increment = () => { count.value++ }

  // 或返回响应式方法
  const reset = () => { count.value = 0 }

  return { count, increment, reset }
}

五、逻辑复用(组合函数 useXxx)

这是 setup 最大的优势!把逻辑抽成独立函数:

js 复制代码
// useCounter.js
import { ref } from 'vue'

export function useCounter(initialValue = 0) {
  const count = ref(initialValue)
  const increment = () => count.value++
  const decrement = () => count.value--

  return { count, increment, decrement }
}
javascript 复制代码
<!-- 组件中使用 -->
<script setup>
import { useCounter } from './useCounter'

const { count, increment, decrement } = useCounter(10)
</script>

<template>
  <p>{{ count }}</p>
  <button @click="increment">+1</button>
  <button @click="decrement">-1</button>
</template>

🎯 多个组件可以复用同一个 useXxx,代码不重复!


六、setup 的注意事项

规则 说明
❌ 不能用 this setup 中 thisundefined
✅ 返回值暴露给模板 return { xxx }<script setup> 自动暴露
⚠️ 不要解构 props 会丢失响应性,用 toRefs()
⚠️ 不要解构 context.attrs/slots 它们是非响应式的
🔄 异步支持 可以返回 Promise,配合 <Suspense> 使用
📦 Vue2 选项可访问 setup 但 setup 不能访问 Vue2 的 data/methods

七、完整示例

javascript 复制代码
<template>
  <div class="user-card">
    <h2>{{ user.name }} - {{ user.age }}岁</h2>
    <p>双倍年龄:{{ doubleAge }}</p>
    <button @click="increment">年龄+1</button>
    <button @click="changeName">改名</button>
    <slot></slot>
  </div>
</template>

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

// ✅ 接收 props
const props = defineProps({
  initialName: { type: String, default: '未知' }
})

// ✅ 响应式数据
const user = reactive({
  name: props.initialName,
  age: 18
})

// ✅ 计算属性
const doubleAge = computed(() => user.age * 2)

// ✅ 方法
const increment = () => { user.age++ }
const changeName = () => { user.name = '新名字' }

// ✅ 侦听
watch(() => user.age, (newAge) => {
  console.log(`年龄变为 ${newAge}`)
})

// ✅ 生命周期
onMounted(() => {
  console.log('组件挂载了!')
})

// ✅ 触发事件(给父组件)
const emit = defineEmits(['age-changed'])
</script>

<style scoped>
.user-card {
  padding: 20px;
  border: 1px solid ccc;
  border-radius: 8px;
}
</style>

📋 一图总结

复制代码
setup()
├── 📥 参数:props(父传子数据)+ context(attrs/slots/emit)
├── 📦 声明:ref / reactive(响应式数据)
├── 🧮 计算:computed(派生值)
├── 👀 侦听:watch(数据变化)
├── 🔄 生命周期:onMounted / onUnmounted 等
├── 🛠️ 方法:普通函数 / 箭头函数
├── 📤 返回:暴露给模板使用
└── 🔁 复用:抽成 useXxx 组合函数

💡 总结一句话:setup 就是 Vue 3 的"大脑",把组件的数据、方法、生命周期全部组织在一个函数里,比 Vue 2 更灵活、更好复用!

相关推荐
带娃的IT创业者16 分钟前
Puppeteer 深度解析:超越自动化测试的现代 Web 交互范式
前端·交互·puppeteer·可观测性·浏览器自动化·无头浏览器·web工程化
程序员爱钓鱼18 分钟前
Rust 所有权 Ownership 详解:理解内存安全的核心机制
前端·后端·rust
Mh8 小时前
别再只会 `find` 了:Map 在前端业务里的真实用法
前端·javascript
陈随易9 小时前
FFmpeg 9.0 发布,代号 Lei,音视频处理再升级
前端·后端·程序员
爱丶狸9 小时前
Grafana_Zabbix_ImageRenderer_部署与前端操作手册
linux·前端·zabbix·grafana·kylin
用户0595401744612 小时前
把AI对话记忆存储测试从手工改成Playwright+pytest,覆盖率从20%提到96%,回归时间缩短90%
前端·css
kyriewen12 小时前
别再这样写TypeScript了——Code Review中最常见的8个反模式
前端·javascript·typescript
名字还没想好☜13 小时前
Next.js ‘use client‘ 到底加在哪:Server/Client Components 边界与常见报错
开发语言·前端·javascript·react·next.js
午安~婉13 小时前
GitHub Token/ GitHub Stats统计显示图异常
前端·github·vercel·github token
码云之上13 小时前
AI Agent 工程化总览篇:从 Prompt 到 Harness
前端·人工智能