Vue中如何从父组件获取子组件HTML元素并设置焦点?
Hey there! I totally get why your original approach felt off—digging into $el.firstChild[0] is super brittle, since any change to Cmp2's DOM structure would break it. Let's go with clean, maintainable solutions that follow Vue's component best practices.
Recommended Solution: Expose a Focus Method in Cmp2
The best way is to let Cmp2 handle its own DOM interactions by exposing a public method. This keeps your components decoupled—Cmp1 doesn't need to know anything about Cmp2's internal structure.
Step 1: Update Cmp2 to Add a Focus Method
Add a ref to the input element and create a method to trigger focus:
<template> <div class="search-bar"> <input ref="searchInput" type="text" placeholder="Search..."> </div> </template> <script> export default { name: 'Cmp2', methods: { // Public method to focus the input focusSearchInput() { this.$nextTick(() => { this.$refs.searchInput.focus(); }); } } } </script>
Step 2: Call the Method from Cmp1
In Cmp1, use a ref on Cmp2 and call the focusSearchInput method after the component mounts:
<template> <div class="cmp1-container"> <Cmp2 ref="searchComponent"></Cmp2> <!-- Your other Cmp1 content here --> </div> </template> <script> import Cmp2 from './Cmp2.vue'; export default { name: 'Cmp1', components: { Cmp2 }, mounted() { // Wait for the DOM to fully render before focusing this.$nextTick(() => { this.$refs.searchComponent.focusSearchInput(); }); } } </script>
Alternative: Use a Prop with Sync for Dynamic Control
If you need to trigger focus dynamically (e.g., not just on mount), use a prop with Vue's sync modifier to communicate between parent and child.
Step 1: Update Cmp2 with a Focus Prop
Add a prop to trigger focus and watch it to activate the input:
<template> <div class="search-bar"> <input ref="searchInput" type="text" placeholder="Search..."> </div> </template> <script> export default { name: 'Cmp2', props: { shouldFocus: { type: Boolean, default: false } }, watch: { shouldFocus(newVal) { if (newVal) { this.$nextTick(() => { this.$refs.searchInput.focus(); // Reset the prop to avoid re-triggering accidentally this.$emit('update:shouldFocus', false); }); } } } } </script>
Step 2: Trigger Focus from Cmp1
Toggle the shouldFocus prop in Cmp1's mounted hook:
<template> <div class="cmp1-container"> <Cmp2 :shouldFocus.sync="triggerSearchFocus"></Cmp2> </div> </template> <script> import Cmp2 from './Cmp2.vue'; export default { name: 'Cmp1', components: { Cmp2 }, data() { return { triggerSearchFocus: false }; }, mounted() { this.$nextTick(() => { this.triggerSearchFocus = true; }); } } </script>
Result Screenshot
Once implemented, you'll see the search input in Cmp2 automatically get focus right after Cmp1 finishes rendering. Here's what that looks like:

内容的提问来源于stack exchange,提问作者YEVY

