Vue3核心概念之构造函数和普通函数

这是 Vue 3 组合式 API 中非常核心且重要的概念。在 Vue 3中,构造函数普通函数在组合式函数(Composables)和组件生命周期中有着天壤之别。

简单来说,关键在于调用时机执行上下文(this


核心区别总结

特性 构造函数 (以 new 调用) 普通函数 (直接调用)
调用方式 new ClassName() functionName()
this 指向 指向新创建的实例对象 默认指向调用者 (严格模式下为 undefined)
返回值 默认返回新创建的实例 返回 return 语句的值,默认为 undefined
主要目的 创建和初始化一个对象实例 执行一个过程或计算一个值

在 Vue 3 上下文中的具体体现

在 Vue 2 中,我们大量使用 new Vue() 来创建应用实例,并使用 new 来创建组件构造函数。但在 Vue 3 的 Composition API 世界里,我们更多地与普通函数打交道。

1. 应用和组件实例的创建 (构造函数)

Vue 3 应用本身仍然是通过构造函数模式创建的,但这被框架隐藏了。

  • createApp : 看起来是一个普通函数,但它内部实际上抽象了 new 的操作 ,返回一个应用实例

    javascript 复制代码
    import { createApp } from 'vue'
    import App from './App.vue'
    
    // createApp 函数内部处理了实例化逻辑,返回一个应用实例对象
    const app = createApp(App) // 类似于 const app = new VueAppConstructor(App)
    app.mount('#app')
  • Vue.extend() (Vue 2) vs 单文件组件 (Vue 3) : 在 Vue 2 中,我们可以用 const Component = Vue.extend({...}) 创建一个组件构造函数 ,需要 new Component() 来实例化。而在 Vue 3 中,我们写的 .vue 单文件组件被 vue-loader 处理,最终也会被转换成一个用于创建组件虚拟节点的构造函数,但这个过程对开发者是透明的。

2. 组合式函数 (Composables) (普通函数)

这是 Vue 3 的核心特性。组合式函数就是普通函数 ,它们内部使用 Vue 提供的 API(如 ref, reactive, onMounted)。

javascript 复制代码
// composables/useMouse.js
import { ref, onMounted, onUnmounted } from 'vue'

// 这是一个普通函数!绝不是构造函数。
export function useMouse() {
  // 在函数内部定义响应式状态
  const x = ref(0)
  const y = ref(0)

  // 在函数内部定义生命周期钩子
  function update(event) {
    x.value = event.pageX
    y.value = event.pageY
  }

  onMounted(() => window.addEventListener('mousemove', update))
  onUnmounted(() => window.removeEventListener('mousemove', update))

  // 返回响应式状态
  return { x, y }
}

在组件中使用:

vue 复制代码
<script setup>
import { useMouse } from './composables/useMouse'

// 普通函数调用!每次调用都会创建一套独立的响应式状态和生命周期钩子。
const { x, y } = useMouse()
</script>

<template>Mouse position is at: {{ x }}, {{ y }}</template>

关键点

  • useMouse 是一个普通函数 ,直接调用 useMouse()
  • 每次调用都会执行函数体,创建新的 ref 变量和新的 生命周期钩子,从而实现了状态的逻辑复用与隔离
  • 如果它被设计成构造函数(new UseMouse()),用法会变得非常笨重和奇怪,完全违背了组合式 API 的简洁理念。
3. 生命周期钩子 (普通函数)

Vue 3 的生命周期钩子都是普通函数 ,它们必须在同步的setup执行期间被调用。

vue 复制代码
<script setup>
import { onMounted } from 'vue'

// 正确:普通函数调用,直接注册生命周期回调
onMounted(() => {
  console.log('组件挂载完毕!')
})
</script>

你不能写 new onMounted(...),这会直接报错。

4. 响应式 API (普通函数)

ref, reactive, computed 等都是普通工厂函数,用于创建响应式对象。

javascript 复制代码
import { ref, reactive } from 'vue'

// 普通函数调用,返回一个响应式引用对象
const count = ref(0)
// 普通函数调用,返回一个响应式代理对象
const state = reactive({ count: 0 })

为什么 Vue 3 更推崇普通函数?

Vue 3 的 Composition API 设计哲学是逻辑关注点分离更好的代码组织与复用

  1. 更好的类型推断: 普通函数对 TypeScript 的支持极其友好,不需要复杂的泛型和构造函数重载。
  2. 更小的体积和更好的压缩 : 函数名(如 ref)可以被压缩工具安全地重命名(mangle),而构造函数名(如 Vue)通常需要保留。
  3. 更灵活的逻辑组合: 普通函数可以轻松地在任何地方(不仅是组件中)被调用和组合,比如在其他函数内部、条件语句中等,提供了极大的灵活性。
  4. 更低的认知负担 : 无需理解 newprototypethis 绑定等 JavaScript 构造函数相关的复杂概念,只需要会写函数和变量即可。
  5. Tree-shaking 友好: 打包工具可以更容易地检测和移除未使用的导出函数,减小最终打包体积。

结论

在 Vue 3 开发中,你的日常绝大部分工作都是在与普通函数 打交道:调用 ref()onMounted()、自己编写 useXXX() 组合式函数。

构造函数 的概念已经被框架底层封装和抽象(如 createApp 和组件编译),开发者几乎不需要直接使用 new 关键字。这种从"基于构造函数和原型"到"基于普通函数和闭包"的转变,是 Vue 3 组合式 API 现代化和强大功能的基础。