setup 中获取组件实例

Vue 3 setup 函数中获取组件实例的方法

问题

Vue 3 的 setup 函数中 thisundefined,如何获取组件实例?

解答

使用 getCurrentInstance

import { getCurrentInstance, onMounted } from 'vue'

export default {
  setup() {
    // 获取当前组件实例
    const instance = getCurrentInstance()
    
    // proxy 是组件的公开实例,类似 Vue 2 的 this
    const proxy = instance?.proxy
    
    onMounted(() => {
      // 访问组件属性
      console.log(proxy?.$el)
      console.log(proxy?.$attrs)
      console.log(proxy?.$slots)
    })
    
    return {}
  }
}

<script setup> 中使用

<script setup>
import { getCurrentInstance, onMounted } from 'vue'

const instance = getCurrentInstance()

onMounted(() => {
  // 通过 proxy 访问实例属性
  console.log(instance.proxy.$el)
})
</script>

更推荐的替代方案

<script setup>
import { useAttrs, useSlots, ref } from 'vue'

// 获取 attrs
const attrs = useAttrs()

// 获取 slots
const slots = useSlots()

// 获取 DOM 元素用 ref
const elementRef = ref(null)
</script>

<template>
  <div ref="elementRef">内容</div>
</template>

getCurrentInstance 返回值结构

const instance = getCurrentInstance()

// instance 包含:
// - proxy: 组件公开实例(推荐使用)
// - ctx: 组件上下文
// - props: 组件 props
// - emit: 触发事件的方法
// - attrs: 非 props 的属性
// - slots: 插槽

关键点

  • setupthisundefined,需要用 getCurrentInstance() 获取实例
  • 使用 instance.proxy 访问公开实例,而不是直接用 instance
  • getCurrentInstance 只能在 setup 或生命周期钩子中调用
  • 这是内部 API,官方不推荐在应用代码中使用,优先用 useAttrsuseSlotsref 等替代
  • 生产环境中 instance.ctx 会被精简,应使用 proxy 而非 ctx