Vue3选项式API:如何从父组件访问子组件中的元素
从父组件操作子组件元素的解决方案
你的问题核心是父组件无法直接访问子组件内部的DOM元素ref,因为子组件的ref属于其内部作用域。下面给你两种可行的实现方式:
方式一:通过子组件的ref访问内部元素
修改父组件
给循环的子组件绑定统一的ref(循环后会生成数组),再通过子组件实例的$refs获取内部input:
import InputText from "./InputText.js"; export default { components: { InputText }, template: ` {{ things }}<br><br> <!-- 给子组件加ref="inputTexts",循环后生成组件实例数组 --> <input-text v-for="thing in things" :key="thing.id" :thing="thing" ref="inputTexts" /> <br><br> <button @click="focusBox()">TEST</button> `, data() { return { things: [{ "id": 1, "name": "" }, { "id": 2, "name": "" }, { "id": 3, "name": "" }] } }, methods: { focusBox() { // 筛选出id为2的子组件实例 const targetComponent = this.$refs.inputTexts.find(item => item.thing.id === 2); // 通过子组件内部的refs获取input并执行聚焦 targetComponent.$refs[`thing_${targetComponent.thing.id}`].focus(); } } }
子组件保持不变
你原来的动态ref写法是正确的,无需修改:
export default { template: ` <input type="text" v-model="thing.name" :ref="'thing_' + thing.id"> <br> `, props: { thing: Object } }
方式二:子组件暴露方法给父组件调用(更推荐,符合组件封装原则)
这种方式不需要父组件直接操作子组件DOM,而是由子组件提供方法,父组件调用即可,更符合Vue的组件通信规范。
修改子组件
添加一个focusInput方法,负责聚焦内部的input元素:
export default { template: ` <input type="text" v-model="thing.name" :ref="'thing_' + thing.id"> <br> `, props: { thing: Object }, methods: { focusInput() { this.$refs[`thing_${this.thing.id}`].focus(); } } }
修改父组件
同样给子组件绑定ref数组,找到目标组件后直接调用其暴露的方法:
import InputText from "./InputText.js"; export default { components: { InputText }, template: ` {{ things }}<br><br> <input-text v-for="thing in things" :key="thing.id" :thing="thing" ref="inputTexts" /> <br><br> <button @click="focusBox()">TEST</button> `, data() { return { things: [{ "id": 1, "name": "" }, { "id": 2, "name": "" }, { "id": 3, "name": "" }] } }, methods: { focusBox() { const targetComponent = this.$refs.inputTexts.find(item => item.thing.id === 2); targetComponent.focusInput(); } } }
你之前写法失败的原因
你尝试的this.$refs.thing_2.focus()无效,是因为thing_2是子组件内部定义的ref,父组件的$refs只会包含自己模板里声明的ref,无法直接获取子组件内部的DOM引用。
内容的提问来源于stack exchange,提问作者Alex
相关产品推荐
相关产品推荐

