ExtJS 4.0.5中拖拽后重新聚焦TextArea的问题求助
解决ExtJS拖拽后TextArea无法重新聚焦的问题
我完全懂你遇到的这个坑!之前做ExtJS项目时也碰到过一模一样的情况——在notifyDrop里直接调用focus()毫无反应,但控制台手动敲代码却能正常生效,核心原因是拖拽事件的处理流程还没完全结束,浏览器此时还在维护拖拽相关的焦点锁定状态,这时候你调用focus()会被浏览器的事件优先级机制直接忽略。
下面给你几个亲测有效的解决方案:
1. 用setTimeout延迟执行聚焦(最简单的方案)
把focus()放到下一个事件循环里执行,让浏览器先处理完拖拽的所有状态,再执行聚焦操作:
notifyDrop: function (ddSource, e, data) { // 你的内容插入逻辑(正常保留) var textarea = Ext.getCmp("textAreaID"); // 延迟0毫秒即可,把任务放到事件队列末尾 setTimeout(function() { textarea.focus(); }, 0); }
2. 使用ExtJS自带的Ext.defer(更贴合Ext生态)
ExtJS提供了Ext.defer方法,原理和setTimeout类似,但可以更方便地绑定作用域:
notifyDrop: function (ddSource, e, data) { var textarea = Ext.getCmp("textAreaID"); // 内容插入逻辑... // 延迟10毫秒足够确保拖拽事件完全结束 Ext.defer(function() { textarea.focus(); }, 10, this); // 第三个参数绑定当前作用域,方便后续扩展操作 }
3. 额外优化:恢复原光标位置
如果你还需要还原拖拽前的光标位置,记得在拖拽开始前先保存光标位置,再在聚焦后恢复:
// 先在Grid的拖拽开始事件中保存光标位置 var savedCursorPos; yourGridPanel.on('dragstart', function() { var textarea = Ext.getCmp("textAreaID"); if (textarea.hasFocus) { // 获取原生DOM元素的光标起始位置 savedCursorPos = textarea.getEl().dom.selectionStart; } }); // 然后在notifyDrop的延迟函数中恢复光标 notifyDrop: function (ddSource, e, data) { var textarea = Ext.getCmp("textAreaID"); // 内容插入逻辑... Ext.defer(function() { textarea.focus(); // 如果之前保存了光标位置,就精准恢复 if (savedCursorPos !== undefined) { textarea.getEl().dom.setSelectionRange(savedCursorPos, savedCursorPos); savedCursorPos = undefined; // 重置,避免影响后续操作 } }, 10, this); }
至于为什么控制台调用textarea.focus()有效?因为你在控制台执行的时候,整个拖拽事件的处理流程已经完全结束了,浏览器已经回到了正常状态,这时候调用聚焦自然能生效。
内容的提问来源于stack exchange,提问作者Justin H.




