【Vue3基础】组合式API

组合式API

1.前言

在Vue3中,有一项对于开发者来说非常有意义的更新 — 组合式API。

在开始介绍之前,需要注意两点:

  • 选项式API和组合式API是两种不同的风格,但它们不是互斥而是并存的!
  • 在需要大量逻辑组合的场景,往往使用组合式API实现

2.组合式API与选项式API

首先是选项式API,基于这种风格开发的Vue应用如左图所示:

  • 各个选项都有固定的书写位置,如:data — 响应式数据、method — 写方法函数…对于一个功能模块,其相关逻辑的代码是分散的。
  • 优点在于:代码结构清晰
  • 缺点在于:代码组织性差,相似的逻辑代码不方便复用,逻辑复杂时,代码庞大,同一功能模块的上下文代码难以关联

其次是组合式API,基于这种风格开发的Vue应用如右图所示:

  • 特定功能模块的相关代码都可以写在一块儿,同一功能的代码集中。
  • 优点在于:
    • 可以快速定位到某个功能模块的相关代码
    • 当逻辑复杂、代码量较大时,可以进行逻辑拆分、功能封装
      在这里插入图片描述
      当逻辑较为复杂时,我们可以进行功能的抽象和拆分,如下图:
      在这里插入图片描述
2.1 案例

光看图只能做到简单了解,下面我们通过一个具体的实例来体会一下两种开发风格的区别:
在这里插入图片描述

这里有两个独立的功能:

  1. 点击按钮控制div的显示与隐藏
  2. 点击按钮控制div内字体颜色的变化
2.3 利用选项式API实现
<template>
  <div>
    <!-- 功能一模板 -->
    <button @click="show">显示</button>
    <button @click="hide">隐藏</button>
    <div v-if="showDiv">一个被控制显隐的div</div>
  </div>
  <div>
    <!-- 功能二模板 -->
    <button @click="changeRed">红色</button>
    <button @click="changeYellow">蓝色</button>
    <div :style="`color:${fontColor}`">一个被控制字体颜色的的div</div>
  </div>
</template>

<script>
export default {
  name: 'App',
  data() {
    return {
      showDiv: true, // 功能一数据
      fontColor: '' // 功能二数据
    }
  },
  methods: {
    // 功能一方法
    show() {
      this.showDiv = true
    },
    hide() {
      this.showDiv = false
    },
    // 功能二方法
    changeRed() {
      this.fontColor = 'red'
    },
    changeYellow() {
      this.fontColor = 'blue'
    }
  }
}
</script>
2.4 利用组合式API实现
<template>
  <div>
    <!-- 功能一模板 -->
    <button @click="show">显示</button>
    <button @click="hide">隐藏</button>
    <div v-if="showDivFlag">一个被控制显隐的div</div>
  </div>
  <div>
    <!-- 功能二模板 -->
    <button @click="changeRed">红色</button>
    <button @click="changeBlue">蓝色</button>
    <div :style="`color:${fontColor}`">一个被控制字体颜色的的div</div>
  </div>
</template>

<script>
import { ref } from 'vue'
export default {
  name: 'App',
  setup() {
    // 功能一
    const showDivFlag = ref(true)
    function show() {
      showDivFlag.value = true
    }
    function hide() {
      showDivFlag.value = false
    }
    // 功能二

    const fontColor = ref('')
    function changeRed() {
      fontColor.value = 'red'
    }
    function changeBlue() {
      fontColor.value = 'blue'
    }
    return { showDivFlag, show, hide, fontColor, changeRed, changeBlue }
  }
}
</script>

接下来我们对上面的代码进行一下优化:

<script>
import { ref } from 'vue'
function useShow() {
  const showDivFlag = ref(true)
  function show() {
    showDivFlag.value = true
  }
  function hide() {
    showDivFlag.value = false
  }
  return { showDivFlag, show, hide }
}

function useColor() {
  const fontColor = ref('')
  function changeRed() {
    fontColor.value = 'red'
  }
  function changeBlue() {
    fontColor.value = 'blue'
  }
  return { fontColor, changeRed, changeBlue }
}
export default {
  name: 'App',
  setup() {
    // 功能一
    const { showDivFlag, show, hide } = useShow()
    // 功能二
    const { fontColor, changeRed, changeBlue } = useColor()
    return { showDivFlag, show, hide, fontColor, changeRed, changeBlue }
  }
}
</script>

通过定义功能函数,把俩个功能相关的代码各自抽离到一个独立的小函数中,然后通过在 setup 函数中再把俩个小功能函数组合起来,这样一来,我们既可以把 setup 函数变得更为简单清晰,又可以方便维护快速定位功能位置。

当然,这里只是一个小示例而已,在真实的开发过程中,对于多个不同且彼此独立的功能,往往会将其抽象为几个组件,然后分别在对应的组件中编写其内部逻辑代码,最后在父页面中,引入它们的数据、方法,来实现整体需求。

不过,这里并没有涉及到组合式API中的细节,仅仅是进行一个整体的体会。

下面的部分会对组合式API的基础进行简要的介绍。

3.组合式API基础

3.1 setup函数
  1. setup 函数是一个新的组件选项,作为组件中组合式API的起点(入口)
  2. setup 中不能使用thisthis指向undefined
  3. setup函数只会在组件初始化的时候执行一次
  4. setup函数在beforeCreate生命周期钩子执行之前执行

不过现在使用更多的应该是<script setup>语法糖,即下面这种形式:

<script setup>
// 变量
const msg = 'Hello!'
// 函数
function log() {
  console.log(msg)
}
    
//...
</script>

里面的代码会被编译成组件setup()函数的内容。这意味着与普通的<script>只在组件被首次引入的时候执行一次不同,<script setup>中的代码会在每次组件实例被创建的时候执行。

当使用<script setup>的时候,任何在<script setup>声明的顶层的绑定 (包括变量,函数声明,以及 import 引入的内容) 都能在模板中直接使用!

3.2 ref和reactive函数

它们均用于将普通数据转换为响应式数据。

具体内容和区别等可以看这篇文章:【Vue3基础】ref 和 reactive

3.3 toRef函数

toRef方法用于转换响应式对象中的某一个属性单独的响应式数据,并且,这两者的数据是关联的!

<script setup>
import { reactive, toRef } from 'vue'
const obj = reactive({
    name: 'xiaoming',
    info: {
        age: '10',
        sex: 'male',
    },
})

// 如果需要使用info数据,不能直接解构!例如:const { name } = obj
// 因为直接解构出来的数据不再具有响应式的特性,会变成一个普通数据!
// 隐藏这里就需要用toRef函数
const name = toRef(obj, 'name')
const info = toRef(obj, 'info')

// 更新该数据,原本的响应式对象中的对应属性也会变化
const update = () => {
    name.value = 'xiaowang';
    info.value.age = '14';
}

return { name, updateName };
</script>
3.4 toRefs函数

上面说到过,对于响应式对象,如果将其解构或展开,会让数据丢失响应式的能力!

而在某些场景中,解构或展开该对象又是不可避免的,因此,为了解决这个问题,引入了toRefs函数,使用该函数可以保证该对象展开的每个属性都是响应式的。

<script setup>
import { reactive, toRefs } from 'vue'
const obj = reactive({
    name: 'xiaoming',
    info: {
        age: '10',
        sex: 'male',
    },
})

// 这里需要将obj对象的各属性返回,因此使用扩展运算符是最为简单方便的
// 但扩展运算符会导致展开的数据失去响应式特性,所以需要配置toRefs函数使用
return { ...toRefs(obj) };
</script>
3.5 生命周期

在这里插入图片描述

需要注意的是,在组合式API中,可以多次使用同一个生命周期钩子函数,其执行顺序和书写顺序相同。

3.5 补充

首先是关于v-model语法糖调整:

  1. 在vue2.0中v-mode语法糖简写的代码 <Son :value="msg" @input="msg=$event" />
  2. 在vue3.0中v-model语法糖有所调整:<Son :modelValue="msg" @update:modelValue="msg=$event" />

在实际应用中,常常用在父子组件通信中,通过在子组件身上绑定:modelValue="msg"来传递数据,子组件中则在适当的地方用emit('update:modelValue', xxx)更新数据(也可以理解为向父组件传递数据)。

其次是一些其它内容:

Vue3中的 computed、watch 和 watchEffect — 【Vue3基础】Vue3中的 computed、watch 和 watchEffect

Vue3 组件通信 — 【Vue3基础】Vue3 组件间通信

Vue3 Provide/Inject — 【Vue3基础】依赖注入 — Provide/Inject

Vue3 mixins —

<think>嗯,用户问的是Vue3组合式API,我需要先回忆一下相关知识。组合式APIVue3的重要特性,和之前的选项式API有很大不同。首先得明确用户可能的背景,可能是从Vue2转过来的开发者,或者刚接触Vue3,想了解新特性。 我应该从基本概念开始介绍,说明组合式API是什么,为什么引入它。然后对比选项式API,比如逻辑复用困难的问题,组合式API如何解决。可能需要举例子,比如使用setup函数,还有响应式API如ref和reactive的区别。 然后要讲到生命周期钩子的变化,如何在组合式API中使用。还有计算属性和侦听器的写法,比如computed和watch函数。可能用户也会关心如何组织代码,比如将逻辑提取到组合函数中,提高复用性。 还要注意用户可能对语法细节不熟悉,比如script setup的语法糖,这样可以让代码更简洁。另外,组合式API带来的更好的TypeScript支持也是一个点,需要提到。 要确保语言通俗易懂,避免太专业的术语,但也要准确。结构上分点说明,比如核心概念、优势、示例等。最后可能加上一个简单的代码示例,展示基本用法,帮助用户直观理解。 检查有没有遗漏的重要点,比如响应式原理的变化,或者与Vue2的兼容性。组合式API不是必须使用的,而是为了更好的组织和复用代码,所以应该提到可以根据项目需要选择使用。 最后确认回答符合格式要求,使用中文,数学公式正确,但这个问题可能不需要太多公式,更多是代码和结构说明。确保LaTeX格式正确,如果有的话。现在组织内容,分步骤介绍组合式API的核心概念和用法。</think>Vue3组合式API(Composition API)是Vue3的核心特性之一,它通过更灵活的代码组织方式解决了复杂组件的逻辑复用和代码可读性问题。以下分步说明其核心要点: --- ### 一、与选项式API对比 **传统选项式APIVue2)** 将代码按功能选项划分(`data`, `methods`, `computed`等),当组件复杂时: 1. 同一功能的代码分散在不同选项中 2. 逻辑复用依赖mixins(易产生命名冲突) **组合式APIVue3)** 允许按逻辑功能组织代码: ```javascript // 示例:计数器逻辑封装 function useCounter() { const count = ref(0) const increment = () => count.value++ return { count, increment } } ``` --- ### 二、核心API 1. **`setup()` 函数** - 组件入口函数,在`beforeCreate`之前执行 - 接收`props`和`context`参数 - 返回对象中的属性会暴露给模板 2. **响应式系统** - `ref()`: 处理基本类型/对象,通过`.value`访问 - `reactive()`: 创建对象响应式代理 ```javascript const num = ref(0) // 访问需用num.value const state = reactive({ count: 1 }) // 直接访问state.count ``` 3. **生命周期钩子** 通过`onX`形式引入: ```javascript import { onMounted } from &#39;vue&#39; setup() { onMounted(() => { console.log(&#39;组件已挂载&#39;) }) } ``` 4. **计算与侦听** - `computed()`: 计算属性 - `watch()`/`watchEffect()`: 响应式侦听 ```javascript const doubled = computed(() => count.value * 2) watch(count, (newVal) => { console.log(&#39;count变化:&#39;, newVal) }) ``` --- ### 三、优势特性 1. **逻辑复用** 可将功能封装为组合函数(如`useFetch`, `useMouseTracker`) ```javascript // 复用数据请求逻辑 function useFetch(url) { const data = ref(null) const fetchData = async () => { data.value = await axios.get(url) } return { data, fetchData } } ``` 2. **TypeScript支持** 更好的类型推断: ```typescript interface User { id: number name: string } const user = ref<User>({ id: 1, name: &#39;John&#39; }) ``` 3. **代码组织** 相关逻辑可以集中管理: ```javascript setup() { // 用户认证逻辑组 const { user, login } = useAuth() // 数据获取逻辑组 const { posts, loadPosts } = usePosts() return { user, login, posts, loadPosts } } ``` --- ### 四、最佳实践示例 ```vue <script setup> <!-- 语法糖模式 --> import { ref, computed } from &#39;vue&#39; const count = ref(0) const doubled = computed(() => count.value * 2) function increment() { count.value++ } </script> <template> <button @click="increment"> 点击次数:{{ count }},双倍:{{ doubled }} </button> </template> ``` --- ### 五、适用场景 1. 中大型复杂组件开发 2. 需要跨组件复用的逻辑 3. 需要更好TypeScript支持的项目 4. 团队追求更灵活的代码组织方式 通过组合式API,开发者可以像搭积木一样自由组合逻辑功能,同时保持更好的类型支持和可维护性。建议新项目优先采用,老项目可逐步迁移。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值