React动态生成input输入框新增后如何聚焦?选ID、ref还是name?
React可扩展列表新增项自动聚焦实现方案
你之前对ref的用法存在误解,createRef 不强制要求和变量同名,完全可以把ref存在数组、对象这类集合里动态存取。这里提供两种可直接落地的实现思路:
方案1:动态Ref(React官方推荐,稳定性更高)
实现步骤:
- 类组件初始化时创建ref存储容器
constructor(props) { super(props); // 用对象存储所有输入框的ref,key为动态生成的唯一标识 this.emailInputRefs = {}; }
- 渲染列表时给每个输入框绑定动态ref
<input // 原有id属性可以保留,也可以删掉 id={"pickup_mail_"+index} // 新增动态ref绑定 ref={el => this.emailInputRefs[`${emailType.toLowerCase()}_mail_${index}`] = el} className="form-control" disabled={this.props.parentProps.IsApproved} type="text" value={item.Email} onChange={e => (item.Email = e.target.value, this.forceUpdate())} onBlur={() => this.validateAdditionalEmails()} />
- 新增点击事件中完成聚焦逻辑
additionalEmailClick(event: any, emailType: string) { event.preventDefault(); this.props.updateList('AdditionalEmails', this.extendedEmailList(emailType)); // 计算过滤后列表的最后一项索引 const targetList = this.props.parentProps.AdditionalEmails.filter(x => x.EmailType === emailType); const lastIndex = targetList.length - 1; const refKey = `${emailType.toLowerCase()}_mail_${lastIndex}`; // 加0ms延迟等待React完成DOM渲染 setTimeout(() => { this.emailInputRefs[refKey]?.focus(); }, 0); }
方案2:ID直接查找(无需修改现有渲染逻辑,快速实现)
你现有代码已经给输入框设置了唯一ID,直接用DOM API查找即可,无需修改ref相关逻辑:
additionalEmailClick(event: any, emailType: string) { event.preventDefault(); this.props.updateList('AdditionalEmails', this.extendedEmailList(emailType)); const targetList = this.props.parentProps.AdditionalEmails.filter(x => x.EmailType === emailType); const lastIndex = targetList.length - 1; setTimeout(() => { const lastInput = document.getElementById(`${emailType.toLowerCase()}_mail_${lastIndex}`); lastInput?.focus(); }, 0); }
注意事项
- 加
setTimeout(()=>{},0)的原因是React的状态更新、DOM重渲染属于异步任务,需要等当前同步代码执行完成后DOM才会更新,加延迟可以确保查找元素时新增项已经被渲染到页面上。 - 长期使用推荐给每个邮箱条目加唯一业务ID替代索引作为标识,避免删除条目后索引错乱导致聚焦到错误元素的问题。
内容的提问来源于stack exchange,提问作者Sonnich Jensen
相关产品推荐
相关产品推荐

