前端vue3的setup如何使用

发布时间:2022-02-21 09:44:52 作者:iii
来源:亿速云 阅读:479
# 前端Vue3的setup如何使用

## 一、setup函数概述

### 1.1 setup函数的诞生背景
Vue 3.0作为新一代前端框架,引入了Composition API这一革命性特性。setup函数正是Composition API的核心入口,它的出现主要解决了以下问题:

1. **逻辑关注点分离**:Options API在复杂组件中会导致相同逻辑分散在不同选项中
2. **更好的类型推断**:对TypeScript支持更加友好
3. **逻辑复用能力**:通过组合函数实现更好的逻辑复用
4. **更灵活的代码组织**:可以按逻辑而非选项类型组织代码

### 1.2 setup函数的基本特性
```javascript
import { ref, reactive } from 'vue'

export default {
  setup(props, context) {
    // 响应式状态
    const count = ref(0)
    const state = reactive({ name: 'Vue' })
    
    // 方法
    function increment() {
      count.value++
    }
    
    // 生命周期钩子
    onMounted(() => {
      console.log('组件已挂载')
    })
    
    // 返回模板使用的数据和方法
    return {
      count,
      state,
      increment
    }
  }
}

setup函数具有以下关键特点: - 在组件创建之前执行(在beforeCreate之前) - 接收propscontext两个参数 - 返回的对象将暴露给模板和组件实例 - 内部可以访问组件的生命周期钩子

二、setup参数详解

2.1 props参数

export default {
  props: {
    title: String,
    user: {
      type: Object,
      required: true
    }
  },
  setup(props) {
    console.log(props.title)
    // 注意:props是响应式的,但不要解构它!
    const { user } = toRefs(props)
    return { user }
  }
}

注意事项: - props是响应式的,但不要直接解构(会失去响应性) - 使用toRefs转换后再解构 - props在子组件中不可修改(保持单向数据流)

2.2 context参数

setup(props, context) {
  // 属性(非响应式对象)
  console.log(context.attrs)
  
  // 插槽(非响应式对象)
  console.log(context.slots)
  
  // 触发事件(方法)
  console.log(context.emit)
  
  // 暴露公共属性(方法)
  console.log(context.expose)
}

context对象包含: - attrs:未在props中声明的属性 - slots:父组件传入的插槽内容 - emit:触发自定义事件的方法 - expose:暴露公共属性的方法

三、响应式系统在setup中的使用

3.1 ref与reactive

import { ref, reactive } from 'vue'

setup() {
  // 基本类型使用ref
  const count = ref(0)
  
  // 引用类型可使用reactive
  const state = reactive({
    name: 'Vue 3',
    version: '3.2.0'
  })
  
  // 修改值
  count.value = 1
  state.name = 'Vue.js'
  
  return { count, state }
}

对比说明:

特性 ref reactive
适用类型 基本/引用类型 仅引用类型
访问方式 通过.value 直接访问
解构响应性 保持 丢失
模板中使用 自动解包.value 直接访问

3.2 computed计算属性

import { ref, computed } from 'vue'

setup() {
  const firstName = ref('张')
  const lastName = ref('三')
  
  // 计算属性
  const fullName = computed(() => {
    return `${firstName.value}${lastName.value}`
  })
  
  // 可写的计算属性
  const writableFullName = computed({
    get: () => `${firstName.value}${lastName.value}`,
    set: (newValue) => {
      [firstName.value, lastName.value] = newValue.split(' ')
    }
  })
  
  return { fullName, writableFullName }
}

3.3 watch与watchEffect

import { ref, watch, watchEffect } from 'vue'

setup() {
  const count = ref(0)
  const state = reactive({ name: 'Vue' })
  
  // 基本watch用法
  watch(count, (newVal, oldVal) => {
    console.log(`count变化: ${oldVal} -> ${newVal}`)
  })
  
  // 监听多个源
  watch([count, () => state.name], ([newCount, newName]) => {
    console.log(`count或name变化`, newCount, newName)
  }, { deep: true })
  
  // watchEffect自动追踪依赖
  watchEffect(() => {
    console.log('count或name变化:', count.value, state.name)
  })
  
  return { count, state }
}

四、生命周期钩子的使用

4.1 生命周期映射表

Options API Composition API
beforeCreate 不需要(setup替代)
created 不需要(setup替代)
beforeMount onBeforeMount
mounted onMounted
beforeUpdate onBeforeUpdate
updated onUpdated
beforeUnmount onBeforeUnmount
unmounted onUnmounted
errorCaptured onErrorCaptured
renderTracked onRenderTracked
renderTriggered onRenderTriggered

4.2 实际使用示例

import { onMounted, onUpdated, onUnmounted } from 'vue'

setup() {
  onMounted(() => {
    console.log('组件挂载完成')
    // 执行DOM操作或API请求
  })
  
  onUpdated(() => {
    console.log('组件已更新')
  })
  
  onUnmounted(() => {
    console.log('组件即将卸载')
    // 清理定时器、取消订阅等
  })
}

五、模板引用与组件通信

5.1 模板引用(ref)

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

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

export default {
  setup() {
    const inputRef = ref(null)
    
    onMounted(() => {
      inputRef.value.focus()
    })
    
    return { inputRef }
  }
}
</script>

5.2 组件通信

// 子组件 Child.vue
export default {
  setup(props, { emit }) {
    const sendMessage = () => {
      emit('message', 'Hello from child!')
    }
    
    return { sendMessage }
  }
}

// 父组件 Parent.vue
<template>
  <Child @message="handleMessage" />
</template>

<script>
export default {
  setup() {
    const handleMessage = (msg) => {
      console.log(msg) // 'Hello from child!'
    }
    
    return { handleMessage }
  }
}
</script>

六、高级用法与最佳实践

6.1 组合式函数

// useCounter.js
import { ref } from 'vue'

export function useCounter(initialValue = 0) {
  const count = ref(initialValue)
  
  function increment() {
    count.value++
  }
  
  function decrement() {
    count.value--
  }
  
  function reset() {
    count.value = initialValue
  }
  
  return { count, increment, decrement, reset }
}

// 组件中使用
import { useCounter } from './useCounter'

export default {
  setup() {
    const { count, increment } = useCounter(10)
    return { count, increment }
  }
}

6.2 类型推断与TypeScript

import { defineComponent, ref } from 'vue'

interface User {
  name: string
  age: number
}

export default defineComponent({
  props: {
    message: {
      type: String,
      required: true
    }
  },
  setup(props) {
    const count = ref<number>(0)
    const user = ref<User>({ name: 'Alice', age: 25 })
    
    return { count, user }
  }
})

6.3 性能优化建议

  1. 避免不必要的响应式:静态数据不要用ref/reactive包装
  2. 合理使用shallowRef/shallowReactive:对于不需要深度响应的大对象
  3. watch优化:明确指定deep和immediate选项
  4. 计算属性缓存:优先使用computed而非方法
  5. 组件分割:将复杂组件拆分为多个小组件

七、常见问题与解决方案

7.1 响应式丢失问题

// 错误做法
setup() {
  const state = reactive({ count: 0 })
  return {
    ...state // 响应性丢失!
  }
}

// 正确做法1
setup() {
  const state = reactive({ count: 0 })
  return {
    state // 保持响应性
  }
}

// 正确做法2
import { toRefs } from 'vue'
setup() {
  const state = reactive({ count: 0 })
  return {
    ...toRefs(state) // 转换为ref
  }
}

7.2 异步组件与setup

import { defineAsyncComponent } from 'vue'

const AsyncComp = defineAsyncComponent(() =>
  import('./components/AsyncComponent.vue')
)

// 在setup中使用
setup() {
  return {
    AsyncComp
  }
}

7.3 与Vuex/Pinia配合使用

import { useStore } from 'vuex'

export default {
  setup() {
    const store = useStore()
    
    const count = computed(() => store.state.count)
    
    function increment() {
      store.commit('increment')
    }
    
    return { count, increment }
  }
}

八、总结与展望

Vue 3的setup函数为组件开发带来了全新的编程范式,通过本文我们全面了解了:

  1. setup函数的基本用法和核心概念
  2. 响应式系统的各种API使用场景
  3. 生命周期钩子的迁移和最佳实践
  4. 组件通信和模板引用的新方式
  5. 高级模式和常见问题的解决方案

随着Vue 3生态的不断完善,setup语法糖(<script setup>)进一步简化了使用方式,但底层原理与本文介绍的setup函数完全一致。掌握好这些基础知识,将帮助您更好地适应Vue 3的开发模式,构建更健壮、更易维护的前端应用。

未来,Composition API还将继续演进,与Vue的响应式系统、编译器优化等特性深度整合,为开发者带来更出色的开发体验。建议持续关注Vue官方文档和RFC提案,及时了解最新进展。 “`

推荐阅读:
  1. 怎么在vue3中使用setup、 ref、reactive
  2. 如何在vue3中使用setup、 ref、reactive

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

vue3 setup

上一篇:Java中怎么用lambda表达式实现aop切面功能

下一篇:vue架构插槽slot如何使用

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》