1. ref + defineExpose (recommended solution)
Accurate access through a combined API, which is the core method officially recommended by Vue3:
<!-- Subcomponents --> <script setup> import { ref } from 'vue' const childData = ref('Subcomponent data') const childMethod = () => ('The method is triggered') // Must be exposed to access by parent componentdefineExpose({ childData, childMethod }) </script> <!-- Parent component --> <template> <Child ref="childRef" /> </template> <script setup> import { ref, onMounted } from 'vue' const childRef = ref(null) onMounted(() => { () // Output: Subcomponent data () // Trigger subcomponent method}) </script>
Key points description:
- The subcomponent must pass
defineExpose
Explicit properties/methods - Parent component passes
Pay attention to the life cycle timing when accessing
- Support TS type derivation (need to be used with TypeScript)
2. getCurrentInstance (alternative solution)
Suitable for advanced scenarios where access to component context is required:
// SubcomponentsdefineExpose({ customMethod: () => {} }) // Parent componentimport { getCurrentInstance } from 'vue' const instance = getCurrentInstance() const childComponent = ()
Notes:
- It belongs to the underlying API, and it is recommended to use the ref scheme first
- Component rendering order needs to be strictly guaranteed
- Problems may occur in SSR environment
3. Event-driven mode (props + emit)
Communication methods that comply with the principle of one-way data flow:
<!-- Subcomponents --> <script setup> defineProps(['modelValue']) const emit = defineEmits(['update:modelValue']) const updateData = (val) => { emit('update:modelValue', val) } </script> <!-- Parent component --> <Child :modelValue="parentData" @update:modelValue="handleUpdate"/>
Applicable scenarios:
- One-way flow of data is required
- Form components, etc. need two-way binding
4. Dependency injection mode (provide/inject)
Solve deep nested component access issues:
// Ancestor componentprovide('sharedData', ref('Responsible data')) // Descendant componentsconst data = inject('sharedData')
Advantages:
- Direct access across multiple layers of components
- Implement state sharing with responsive API
5. Status Management Solution (Pinia/Vuex)
Access methods in global state management scenarios:
// store/ export const useUserStore = defineStore('user', { state: () => ({ userInfo: null }) }) //Arbitrary componentsconst store = useUserStore() = 'Global Data'
Applicable scenarios:
- Need to share state across multiple components
- State management of complex applications
Notes and best practices
- One-way data flow principle: Priority is given to props/emit method to pass data
- Encapsulation protection: The minimum API collection that the child component should explicitly expose
- Life cycle timing: Make sure to access ref after onMounted
- TypeScript Support: Use interface to define the exposure type
Plan comparison table
method | Applicable level | Responsive | Maintenance cost | Applicable scenarios |
---|---|---|---|---|
ref + defineExpose | Father and son | ✔️ | Low | Precise method call |
provide/inject | Cross-level | ✔️ | middle | Deep component sharing |
Event-driven | Father and son | ✔️ | Low | Data change notification |
Status Management | Global | ✔️ | high | Complex application state sharing |
This is the end of this article about the five solutions for Vue3 parent component access to child component methods/properties. For more information about Vue3 parent component access to child component methods, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!