In Vue.js you sometimes need to access a child component instance programmatically, for example to call its methods or read its data.
Unlike older frameworks, Vue doesn't encourage querying by component name directly at runtime, but there are ways to access a component instance safely: using $refs, provide/inject, or dynamic rendering patterns. Here’s how it works.
Why Direct Lookup by Name Doesn’t Exist
Vue doesn’t expose a direct API to “get a component by name.” Component names are used for registration and debugging, but not for runtime lookups. Instead, Vue relies on references ($refs), props, or the Composition API for safe communication between components.
Use $refs to Access a Child Component
The standard way to access a child component instance is to use a template ref (ref).
Example:
<!-- ParentComponent.vue --><template>
<ChildComponent ref="myChild" />
<button @click="callChildMethod">Call Child Method</button>
</template>
<script setup>
import { ref, onMounted } from 'vue'
import ChildComponent from './ChildComponent.vue'
const myChild = ref(null)
function callChildMethod() {
if (myChild.value) {
myChild.value.sayHello()
}
}
</script>
<!-- ChildComponent.vue --><script setup>
function sayHello() {
console.log('Hello from Child!')
}
defineExpose({ sayHello })
</script>
How it works:
- Add ref="myChild" to the child in the parent’s template.
- Use defineExpose in the child to expose internal methods or data.
- Access it in the parent via myChild.value.
Use provide and inject
For nested components that aren’t directly parent-child, use Vue’s provide/inject API.
<!-- ParentComponent.vue --><script setup>import { provide, ref } from 'vue'
const myData = ref('Shared Value')
provide('sharedData', myData)
</script>
<!-- DeepChildComponent.vue --><script setup>
import { inject } from 'vue'
const sharedData = inject('sharedData')
console.log(sharedData.value) // 'Shared Value'
</script>
Also Read: The Top Websites Built with Vue JS
Use Dynamic Component Registration
When rendering dynamic components, you can control what gets rendered by name:
<template> <component :is="currentComponent" /></template>
<script setup>
import Foo from './Foo.vue'
import Bar from './Bar.vue'
const currentComponent = 'Foo'
const components = { Foo, Bar }
</script>
Note: You still don’t look up by name at runtime; you control which component is rendered by using a dynamic variable.
Common Pitfalls
- Vue doesn’t have getComponentByName() at runtime.
- Don’t manually walk the virtual DOM to find components, this breaks reactivity and maintainability
- Use $refs for parent-child access only.
- Use provide/inject for deeper or sibling communication.
Key Takeaway
Vue.js doesn’t support runtime lookups by component name because it prefers explicit connections. Use $refs for direct parent-child access, provide/inject for deeper communication, and props/events for predictable data flow.
Related Resources