Vue3系列 - 组件实例与当前实例

2025 年 9 月 28 日 星期日
/
22

Vue3系列 - 组件实例与当前实例

组件实例与当前实例

Vue3的组合式API依赖于当前组件实例的概念,通过currentInstance变量跟踪当前正在执行的组件实例。这对于在setup函数中使用生命周期钩子、依赖注入等功能至关重要。让我们深入了解Vue2.7中组件实例与当前实例的实现。

currentInstance变量

currentInstance是一个全局变量,用于跟踪当前正在执行的组件实例:

// 在currentInstance.ts中
export let currentInstance = null

export function setCurrentInstance(vm = null) {
  currentInstance = vm
}

export function getCurrentInstance() {
  return {
    proxy: currentInstance
  }
}

在setup中设置当前实例

在执行setup函数时,会设置当前实例:

export function initSetup(vm) {
  // ...
  if (setup) {
    // ...
    setCurrentInstance(vm)
    pushTarget()
    const setupResult = invokeWithErrorHandling(
      setup,
      null,
      [vm._props || shallowReactive({}), ctx],
      vm,
      `setup`
    )
    popTarget()
    setCurrentInstance()
    // ...
  }
}

setCurrentInstance(vm)设置当前实例为vm,setCurrentInstance()(不带参数)将当前实例重置为null。

在生命周期钩子中使用当前实例

生命周期钩子函数使用当前实例来注入钩子:

function createLifeCycle(hookName) {
  return (fn, target = currentInstance) => {
    if (!target) {
      __DEV__ &&
        warn(
          `${formatName(hookName)} is called when there is no active component instance to be ` +
            `associated with. ` +
            `Lifecycle injection APIs can only be used during execution of setup().`
        )
      return
    }
    return injectHook(target, hookName, fn)
  }
}

如果没有当前实例(即不在setup函数中调用),则会在开发环境中发出警告。

在依赖注入中使用当前实例

依赖注入(provide/inject)也依赖于当前实例:

export function provide(key, value) {
  if (!currentInstance) {
    // 警告...
  } else {
    // 在当前实例上提供值...
  }
}

export function inject(key, defaultValue) {
  if (!currentInstance) {
    // 警告...
  } else {
    // 从祖先组件获取注入的值...
  }
}

getCurrentInstance API

Vue2.7也提供了getCurrentInstance API,允许在setup函数中获取当前组件实例:

export function getCurrentInstance() {
  return {
    proxy: currentInstance
  }
}

这个API主要用于高级用例和库开发,一般应用开发中应该避免直接使用组件实例。

组件实例的结构

Vue2.7中的组件实例(Component类)包含了组件的所有信息和方法:

export declare class Component {
  constructor(options?: any)
  // 构造信息
  static cid: number
  static options: Record<string, any>
  // 扩展
  static extend: GlobalAPI['extend']
  // ...

  // 公共属性
  $el: any
  $data: Record<string, any>
  $props: Record<string, any>
  $options: ComponentOptions
  $parent: Component | undefined
  $root: Component
  $children: Array<Component>
  $refs: {
    [key: string]: Component | Element | Array<Component | Element> | undefined
  }
  $slots: { [key: string]: Array<VNode> }
  // ...
}

总结

组件实例与当前实例的概念是Vue组合式API的基础。通过currentInstance变量,Vue能够在setup函数中提供生命周期钩子、依赖注入等功能。理解组件实例与当前实例的实现原理,有助于我们更好地使用组合式API,解决组件实例相关的问题。

使用社交账号登录

  • Loading...
  • Loading...
  • Loading...
  • Loading...
  • Loading...