StencilJS中二次渲染组件覆盖首个组件输入框自动聚焦问题
问题根因
- 浏览器的页面焦点是全局唯一资源,同一时间仅能有一个输入类元素持有焦点,你当前给所有
search-input组件都默认配置了加载完成后自动执行聚焦逻辑,后触发聚焦的组件自然会抢占之前组件的焦点。 - Stencil的自定义组件是异步加载渲染的,
componentDidLoad生命周期的触发顺序和DOM标签的书写顺序没有必然绑定,所以每次最后拿到焦点的组件也不固定。
解决方案
最合理的处理方式是给组件增加自动聚焦的开关属性,仅在显式声明需要聚焦的组件上开启该能力:
第一步:修改组件代码,增加autoFocus控制逻辑
import { Component, h, Prop, Event, EventEmitter, Method } from '@stencil/core'; @Component({ tag: 'search-input', styleUrl: 'search-input.css', shadow: true, }) export class SearchInput { private searchInput: HTMLInputElement; @Prop() value = ""; @Prop() dataTestId!: string; @Prop() placeHolder: string = "Search"; // 新增自动聚焦开关,默认关闭 @Prop() autoFocus: boolean = false; @Event() clearSearch: EventEmitter; @Event() searchRequest: EventEmitter; // 可选:对外暴露手动聚焦方法,满足上层自定义触发聚焦的需求 @Method() async setFocus() { this.searchInput?.focus(); } protected componentDidLoad() { // 只有autoFocus为true时才执行自动聚焦 if (this.autoFocus) { this.searchInput.focus(); } } render() { return ( <div data-test-id={this.dataTestId} class="items-center flex bg-white border-solid rounded-sm border-gray-300 box-border text-xl border-1 pl-15 pr-12 py-9"> <input type="text" ref={el => (this.searchInput = el as HTMLInputElement)} data-test-id={`${this.dataTestId}-search-input`} class="focus:outline-none border-0 flex-grow w-full pl-15" value={this.value} placeholder={this.placeHolder} /> </div> ); } }
第二步:使用时按需开启自动聚焦
比如你需要第一个搜索框默认聚焦,就只给第一个组件加auto-focus属性即可:
<!DOCTYPE html> <html dir="ltr" lang="en"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=5.0" /> <title>Stencil Component Starter</title> <script type="module" src="/build/testing.esm.js"></script> <script nomodule src="/build/testing.js"></script> </head> <body> <!-- 仅给需要默认聚焦的组件加auto-focus属性 --> <search-input auto-focus data-test-id="test-two" place-holder="Search" value=""></search-input> <search-input data-test-id="test-three" place-holder="Search" value=""></search-input> </body> </html>
如果有动态切换聚焦的需求,你可以获取对应search-input的DOM实例,调用暴露的setFocus方法手动触发聚焦即可。
内容的提问来源于stack exchange,提问作者MogerCS
相关产品推荐
相关产品推荐

