Ionic 6:如何通知子组件父级ion-modal已呈现并聚焦输入框
解决Ion Modal子组件Input焦点被模态框夺走的问题
问题背景
打开ion-modal时,模态框会夺走子组件中ion-input的焦点。最初在子组件mounted钩子中直接设置焦点无效(因为mounted执行时模态框还未完全呈现),用setTimeout临时可行但存在竞态条件,不够可靠。尝试监听模态框did-present事件时,又无法直接获取子组件实例调用焦点方法。
可靠解决方案
方案一:父组件通过Modal实例调用子组件焦点方法
Ionic的Modal实例提供了componentInstance属性,可直接访问子组件实例,结合did-present事件就能在模态框完全呈现后触发焦点设置:
父组件代码
const modal = await modalController.create({ component: ChildrenCompWithInput, }); // 监听模态框呈现完成事件 modal.addEventListener('did-present', () => { // 调用子组件暴露的焦点方法 modal.componentInstance.setInputFocus(); }); await modal.present();
子组件代码
<template> <ion-input ref="inputElementRef"></ion-input> </template> <script setup lang="ts"> import { ref } from 'vue'; import type { IonInput } from '@ionic/vue'; const inputElementRef = ref<InstanceType<typeof IonInput> | null>(null); // 暴露给父组件调用的焦点设置方法 const setInputFocus = () => { if (inputElementRef.value) { inputElementRef.value.$el.setFocus(); } }; </script>
方案二:子组件内部监听模态框呈现事件
让子组件自身监听模态框的did-present事件,逻辑内聚,无需父组件额外配合:
子组件代码
<template> <ion-input ref="inputElementRef"></ion-input> </template> <script setup lang="ts"> import { ref, onMounted, onUnmounted } from 'vue'; import type { IonInput } from '@ionic/vue'; import { modalController } from '@ionic/vue'; const inputElementRef = ref<InstanceType<typeof IonInput> | null>(null); let presentListener: (() => void) | null = null; onMounted(() => { // 获取当前最上层的模态框实例 const currentModal = modalController.top(); if (currentModal) { presentListener = () => { inputElementRef.value?.$el.setFocus(); }; currentModal.addEventListener('did-present', presentListener); } }); onUnmounted(() => { // 移除监听,避免内存泄漏 const currentModal = modalController.top(); if (currentModal && presentListener) { currentModal.removeEventListener('did-present', presentListener); } }); </script>
方案优势
两种方案都通过did-present事件精准捕捉模态框完全呈现的时机,避免了模态框渲染覆盖焦点的问题,不存在setTimeout的竞态风险,是稳定可靠的实现方式。
内容的提问来源于stack exchange,提问作者Wazime
相关产品推荐
相关产品推荐

