如何从Vue父组件访问子组件中的元素Ref?
How to Access a Child Component's Element Ref from a Parent in Vue 3
嘿,我懂你这个场景——父组件里有个全局按钮,点击后要让子组件里的特定输入框聚焦,对吧?在Vue 3里实现这个需求,有两种主要方式,我给你详细说说,优先推荐第一种,因为更符合Vue的组件封装原则:
方法1:子组件主动暴露聚焦能力(推荐)
这种方式的核心是让子组件自己管理内部元素的ref,然后对外暴露一个聚焦方法,父组件只需要调用这个方法就行,完全不用关心子组件内部的DOM结构,耦合性极低。
子组件代码(比如叫ChildInput.vue)
<template> <input ref="innerInput" placeholder="子组件输入框" /> </template> <script setup> import { ref } from 'vue' // 定义子组件内部的输入框ref const innerInput = ref(null) // 定义聚焦方法 const focusInput = () => { innerInput.value?.focus() } // 把方法暴露给父组件 defineExpose({ focusInput }) </script>
父组件代码
<template> <div> <button @click="focusChildInput">点击聚焦子组件输入框</button> <!-- 给子组件加ref,方便父组件调用其暴露的方法 --> <ChildInput ref="childComp" /> </div> </template> <script setup> import { ref } from 'vue' import ChildInput from './ChildInput.vue' // 定义子组件的ref const childComp = ref(null) // 父组件的点击事件,调用子组件暴露的方法 const focusChildInput = () => { childComp.value?.focusInput() } </script>
方法2:直接访问子组件内部的DOM元素(不推荐)
如果你实在需要直接拿到子组件里的元素ref,可以通过子组件的ref对象直接访问内部的ref,但这种方式会破坏组件的封装性——一旦子组件内部的ref名称或者DOM结构变了,父组件的代码就会报错,所以只建议在简单场景下临时用用。
修改子组件(不需要暴露方法,只保留内部ref)
<template> <input ref="innerInput" placeholder="子组件输入框" /> </template> <script setup> import { ref } from 'vue' const innerInput = ref(null) // 这里需要把内部ref暴露出去,父组件才能拿到 defineExpose({ innerInput }) </script>
父组件代码
<template> <div> <button @click="focusChildInput">点击聚焦子组件输入框</button> <ChildInput ref="childComp" /> </div> </template> <script setup> import { ref } from 'vue' import ChildInput from './ChildInput.vue' const childComp = ref(null) const focusChildInput = () => { // 直接访问子组件暴露的内部ref,然后调用focus childComp.value?.innerInput?.focus() } </script>
为什么推荐第一种方法?
- 符合Vue的组件封装原则:子组件负责自己的DOM操作,父组件只需要调用约定好的方法,不用关心内部实现
- 代码更健壮:子组件内部的DOM结构或者ref名称修改时,只需要同步修改内部的聚焦方法,父组件完全不用改
- 可读性更好:从父组件的代码就能清楚知道,调用的是子组件提供的“聚焦输入框”能力,而不是直接操作DOM
内容的提问来源于stack exchange,提问作者WoJ
相关产品推荐
相关产品推荐

