从Vue选项式API到组合式API,你需要一个优雅的跨越过程
一位前端小姐姐离职2月后,最近刚找到一份新工作。进入岗位后,发现公司的项目都是Vue3开发的,且同事们都使用的是组合式 API (Composition API),这让她很不适应。近日,问我组合式API怎么用? 看来她把组合式的写法当成一种新的语法去学习了,其实不是,这只是一种编程风格而已。不要想象的那么复杂,那么难~。在Vue的官方教程中已经区分出两种风格的写法的,可以自由选择。如果项目中,大家都用组合式API的话,那还是尽量跟大家姿势保持一致吧。写篇文章来给她讲讲,组合式API到底是个什么东西?和选项式API差异又在哪里?对于现在不理解的Vue3的新选手们,也可以自己去搜搜网上资料,了解一下。
Vue.js 是一种流行的前端框架,目前它已经成为了许多Web开发者的首选。在Vue.js 3.0中,推出了新的组合式API,使得开发者能够更加方便灵活地编写Vue组件。这也是组合式 API 成为了 Vue 新的开发范式,与传统的选项 API 相比,组合式 API 更加灵活、易于维护的原因,在大型应用的开发中有着不可替代的优势。在本文中,我们将详细介绍 Vue 组合式API的风格及使用。
一、Vue 组合式API
Vue 组合式API是Vue 3.0中引入的新特性,与之前的Vue选项式API有所不同。组合式API让我们可以根据逻辑而不是按照选项来组织单文件组件。因此,这个新特性使得我们能够更好地封装和重用组件逻辑。Vue 组合式API也让我们能够在不同的组件之间轻松共享代码。
在Vue 组合式API中,每个组件都可以包含一个或多个组合函数。组合函数是普通的JavaScript函数,但可以使用Vue提供的特殊函数和响应性系统。每个组合函数可以返回对象,该对象包含数据属性、计算属性、方法等等,这些都可以在模板中使用。同时,Vue 组合式API还支持生命周期钩子和响应式函数的使用。
在官方文档中对组合式API的讲述也是十分到位,有兴趣的可以看一下:cn.vuejs.org/guide/extra…
二、Vue 组合式API的原理
组合式 API 包含了两个部分:组合式函数和响应式系统。组合式函数是一种特殊的函数,它接收一个上下文对象作为参数,并通过该对象来访问组件的状态和方法。响应式系统是 Vue 3 中引入的新的数据响应机制,它可以实现对数据的自动监听、变更检测和更新视图等功能。
在 Vue 2 中,我们通常使用 Mixin 来实现代码复用。但 Mixin 有其自身的缺点,例如命名冲突、生命周期钩子混乱等问题。为了解决这些问题,Vue 3 引入了组合式函数的概念。组合式函数实际上就是一种特殊的函数,它接收一个上下文对象作为参数,通过该对象可以访问组件的状态和方法。
Vue 组合式API的原理主要是通过两个API: setup()
和 reactive()
实现的。
1. setup()
在 Vue 组合式API 中,每个组件都必须包含一个 setup()
函数。这个函数是在组件初始化期间调用的,其目的是为组件创建并设置响应式状态,并返回需要在模板中使用的数据和方法。 setup()
函数只在组件实例化时执行一次,并返回一个对象。
import { reactive } from 'vue';
export default {
setup() {
const state = reactive({
message: 'Hello World'
});
return {
state
}
}
}
在上面的代码中,我们使用了Vue提供的 reactive()
函数来创建一个响应式对象。在 setup()
函数中,我们将 message
属性保存在 state
对象中,并将其返回到模板中使用。
2. reactive()
Vue 3.0 中的 reactive()
函数是用于创建响应式数据的。响应式数据意味着当数据发生变化时,会自动触发组件重新渲染。在组合式API中使用响应式数据非常简单,只需要使用 reactive()
函数来创建对象即可。
import { reactive } from 'vue';
const state = reactive({
count: 0
});
state.count++; // 触发组件重新渲染
三、使用 Vue 组合式API
现在告诉你如何在Vue组件中使用组合式API。下面是一个简单的例子:
1. 创建组合式函数
学习了官方文档后,你可以简单地编写一个普通的 JavaScript 函数,然后将它返回给 setup()
函数。这个函数可以使用 Vue 提供的特殊函数和响应性系统。同时,组合式函数也可以返回一个对象,该对象包含数据属性、计算属性、方法等等,这些都可以在模板中使用。
<template>
<div>
<p>{{ message }}</p>
<button @click="reverseMessage">Reverse Message</button>
</div>
</template>
<script>
import { reactive } from 'vue';
export default {
setup() {
const state = reactive({
message: 'Hello World'
});
const reverseMessage = () => {
state.message = state.message.split('').reverse().join('');
};
return {
...state,
reverseMessage
};
}
}
</script>
在上面的代码中,我们首先导入了 reactive()
函数,然后在 setup()
函数中使用它创建了一个响应式对象 state
。在这个例子中,我们只有一个属性 message
,初始值为 Hello World
。我们还在 setup()
函数中声明了一个 reverseMessage
函数,该函数通过将 message
属性反转来改变消息文本。
最后,我们从 setup()
函数中返回了一个包含 state
和 reverseMessage
的对象。在模板中,我们使用了插值语法显示了 message
属性,并在按钮上绑定了 reverseMessage
方法。
2. 访问全局状态
在 Vue 2 中,我们通常使用 Vuex 来管理全局状态。但是 Vuex 也有其自身的缺点,例如使用复杂、代码冗余等问题。为了解决这些问题,Vue 3 引入了一个新的 API:provide / inject。使用 provide / inject 可以轻松地实现全局状态的共享和传递。
下面是一个简单的使用 provide / inject 访问全局状态的示例:
import { reactive, provide, inject } from 'vue'
const AppSymbol = Symbol()
export function createAppState() {
const state = reactive({
count: 0
})
provide(AppSymbol, state)
}
export function useAppState() {
const appState = inject(AppSymbol)
if (!appState) {
throw new Error('App state not found')
}
return appState
}
这段代码使用 provide / inject 实现了一个全局状态的共享。createAppState 函数用来创建全局状态,而 useAppState 函数则用来访问全局状态。在组件中使用 useAppState 函数即可访问全局状态。注意,provide 和 inject 必须使用相同的 Symbol 作为键值,以便在不同的文件中进行传递。
3. 处理生命周期
在 Vue 2 中,我们通常使用生命周期钩子函数来处理各种生命周期事件。但是生命周期钩子函数过于繁琐,容易出现潜在的问题。为了解决这些问题,Vue 3 引入了一种新的生命周期处理方式:onXxx 生命周期钩子。
下面是一个简单的使用 onXxx 生命周期钩子的demo:
import { onMounted } from 'vue'
export function useHello() {
onMounted(() => {
console.log('Hello world')
})
}
使用 onMounted 生命周期钩子来实现在组件挂载后输出 "Hello world" 的效果。onMounted 函数接收一个回调函数作为参数,该回调函数将会在组件挂载后执行。通过使用 onXxx 生命周期钩子,我们可以更为灵活地处理各种生命周期事件。
四、组合式 API 和选项式 API 的区别
上面我们已经介绍了选项式 API 和组合式 API 的基本概念和使用方法。那么,这两种 API 之间到底有哪些区别呢?下面是一些常见的区别:
组合式 API 和选项式 API 的背后原理是相似的。它们都依赖于 Vue.js 内部实现的响应式系统。
在 Vue.js 的响应式系统中,Vue.js 使用了 Object.defineProperty 或 Proxy 对象对数据进行监听,当数据发生变化时,Vue.js 就会根据依赖关系重新计算视图,并更新页面。
而在组合式 API 中,Vue.js 将响应式系统的底层实现封装成了一些函数,开发者可以通过这些函数来访问和操作响应式数据。
例如,在组合式 API 中,使用 reactive 函数来创建一个响应式对象。使用 ref 函数来将一个普通的数据转换成响应式数据,使用 computed 函数来定义一个计算属性。
下面简单列举一下差异,让大家明白~
1. API 形式不同
选项式 API 是基于对象的形式,将所有的方法、数据、计算属性等放置在一个对象中。
组合式 API 通过函数的方式组合逻辑代码,可以更容易地实现组件逻辑的复用以及组合。
2. 响应式处理不同
在 Vue.js 2.x 中,选项式 API 使用 Object.defineProperty 来实现数据的响应式处理。
Vue.js 3.x 引入了 Proxy 对象来实现响应式处理。
3. 生命周期钩子不同
在选项式 API 中,生命周期钩子分为两种:beforeCreate 和 created。
在组合式 API 中,生命周期钩子是通过函数的方式来定义的,例如:onBeforeMount、onMounted 等。
4. 计算属性不同
在选项式 API 中,使用 computed 属性来定义计算属性。
在组合式 API 中,使用 computed 函数来定义计算属性。
5. 更小的生产包体积
搭配 <script setup>
使用组合式 API 比等价情况下的选项式 API 更高效,对代码压缩也更友好。这是由于 <script setup>
形式书写的组件模板被编译为了一个内联函数,和 <script setup>
中的代码位于同一作用域。不像选项式 API 需要依赖 this
上下文对象访问属性,被编译的模板可以直接访问 <script setup>
中定义的变量,无需从实例中代理。这对代码压缩更友好,因为本地变量的名字可以被压缩,但对象的属性名则不能。
6. 更好的逻辑复用
组合式 API 最基本的优势是它使我们能够通过组合函数来实现更加简洁高效的逻辑复用。在选项式 API 中我们主要的逻辑复用机制是 mixins,而组合式 API 解决了mixins 的所有缺陷。
从设计者的角度来看,Vue 组合式API和选项式API的区别主要在于它们组织代码的方式和侧重点。
(1)代码组织方式
-
选项式API: 将不同功能的代码分散在不同的选项中,如
data
、computed
、methods
、watch
、created
、mounted
等等。这种方式使得代码结构比较松散,并且难以重用逻辑代码。 -
组合式API: 将不同功能的代码统一放在一个组合函数中。这种方式使得逻辑代码可以更好地封装和重用,同时也使得代码更加结构化和可读性更强。
(2)侧重点
-
选项式API: 强调的是声明式编程,即通过描述组件的属性和方法来定义其行为。这样的做法使得组件的结构和行为都比较清晰明了,但是对于一些复杂逻辑的组件来说,代码可能会比较分散,难以重用。
-
组合式API: 强调的是命令式编程,即通过编写函数来定义组件的行为。这种方式使得逻辑代码更加集中,易于重用,但同时也可能使得组件结构不够清晰,有时候需要适当的抽象和封装。
五、Vue 组合式API的优势
Vue 组合式API带来了许多优点,让我们一起来看看:
-
更好的组件复用 使用选项式API时,我们需要将代码分散在组件选项中。但在组合式API中,我们可以将代码封装在单独的组合函数中,然后在不同的组件之间进行重用。
-
更容易测试 在选项式API中,我们需要模拟Vue实例和其生命周期钩子以进行测试。但在组合式API中,我们可以更轻松地测试组件逻辑,而无需实际创建Vue实例。
-
更好的类型安全 使用选项式API时,我们需要手动添加类型注释以获得类型安全。但在组合式API中,由于其是基于JavaScript函数的,因此能够提供更强大的类型推断和类型安全。
六、小结一下
Vue 组合式API是Vue 3.0 中的一个强大而灵活的特性。它使得我们能够更好地封装和重用组件逻辑,并共享代码。同时,使用Vue 组合式API还能提供更好的类型安全和测试性。在实际开发中,我们应该尽可能地使用Vue 组合式API,以提高开发效率和代码可维护性。
但是? 选项式 API 会被废弃吗?
不会,官方回答:我们没有任何计划这样做。选项式 API 也是 Vue 不可分割的一部分,也有很多开发者喜欢它。我们也意识到组合式 API 更适用于大型的项目,而对于中小型项目来说选项式 API 仍然是一个不错的选择。
👨👩👧👧 其实吧,选项式API适合那些结构比较简单且行为比较明确的组件,而组合式API则更适合那些拥有复杂逻辑,需要更好的代码结构和重用性的组件。当然,在实际开发中,我们也可以根据具体情况灵活选择这两种API,或者将它们结合使用,以便更好地满足项目需求。