@@ -14,6 +14,8 @@ export class InputEditor implements IEditor {
1414 table ?: any ;
1515 col ?: number ;
1616 row ?: number ;
17+ // 存储事件处理器,用于在移除元素前解绑
18+ private eventHandlers : Array < { type : string ; handler : EventListener } > = [ ] ;
1719 constructor ( editorConfig ?: InputEditorConfig ) {
1820 this . editorConfig = editorConfig ;
1921 }
@@ -22,6 +24,9 @@ export class InputEditor implements IEditor {
2224 }
2325
2426 createElement ( ) {
27+ // 清空之前的事件处理器(如果存在)
28+ this . eventHandlers = [ ] ;
29+
2530 const input = document . createElement ( 'input' ) ;
2631 input . setAttribute ( 'type' , 'text' ) ;
2732
@@ -37,37 +42,50 @@ export class InputEditor implements IEditor {
3742 input . style . borderRadius = '0px' ;
3843 input . style . border = '2px solid #d9d9d9' ;
3944 // #region 为了保证input在focus时,没有圆角
40- input . addEventListener ( 'focus' , ( ) => {
45+ const focusHandler = ( ) => {
4146 input . style . borderColor = '#4A90E2' ;
4247 input . style . outline = 'none' ;
43- } ) ;
48+ } ;
49+ input . addEventListener ( 'focus' , focusHandler ) ;
50+ this . eventHandlers . push ( { type : 'focus' , handler : focusHandler } ) ;
4451
45- input . addEventListener ( 'blur' , e => {
52+ const blurHandler : EventListener = ( e : Event ) => {
4653 input . style . borderColor = '#d9d9d9' ;
4754 // input.style.boxShadow = 'none';
48- if ( this . table && this . element . style . opacity === '0' ) {
55+ if ( this . table && this . element && this . element . style . opacity === '0' ) {
4956 const selectCell = this . table . stateManager . select . cellPos ;
5057 if ( selectCell . col !== this . col || selectCell . row !== this . row ) {
5158 this . onEnd ( ) ;
5259 }
5360 }
54- } ) ;
61+ } ;
62+ input . addEventListener ( 'blur' , blurHandler ) ;
63+ this . eventHandlers . push ( { type : 'blur' , handler : blurHandler } ) ;
5564 // #endregion
5665 this . element = input ;
5766 this . container . appendChild ( input ) ;
5867
5968 // 监听键盘事件
60- input . addEventListener ( 'keydown' , ( e : KeyboardEvent ) => {
61- if ( e . key === 'a' && ( e . ctrlKey || e . metaKey ) ) {
69+ const keydownHandler : EventListener = ( e : Event ) => {
70+ const keyboardEvent = e as KeyboardEvent ;
71+ if (
72+ keyboardEvent . key === 'a' &&
73+ ( keyboardEvent . ctrlKey || keyboardEvent . metaKey ) &&
74+ this . table . editorManager ?. editingEditor
75+ ) {
6276 // 阻止冒泡 防止处理成表格全选事件
63- e . stopPropagation ( ) ;
77+ keyboardEvent . stopPropagation ( ) ;
6478 }
65- } ) ;
79+ } ;
80+ input . addEventListener ( 'keydown' , keydownHandler ) ;
81+ this . eventHandlers . push ( { type : 'keydown' , handler : keydownHandler } ) ;
6682
6783 // hack for preventing drag touch cause page jump
68- input . addEventListener ( 'wheel' , e => {
84+ const wheelHandler : EventListener = ( e : Event ) => {
6985 e . preventDefault ( ) ;
70- } ) ;
86+ } ;
87+ input . addEventListener ( 'wheel' , wheelHandler ) ;
88+ this . eventHandlers . push ( { type : 'wheel' , handler : wheelHandler } ) ;
7189 }
7290
7391 setValue ( value : string ) {
@@ -92,6 +110,11 @@ export class InputEditor implements IEditor {
92110 }
93111 if ( ! this . element ) {
94112 this . createElement ( ) ;
113+ } else {
114+ if ( ! container . contains ( this . element ) ) {
115+ this . element . parentElement . removeChild ( this . element ) ;
116+ this . container . appendChild ( this . element ) ;
117+ }
95118 }
96119 this . element . style . opacity = '0' ;
97120 //这个pointerEvents = 'none'很重要,如果没有的话会引起vtable.getElement()元素和这里的element元素的focus和blur的切换,
@@ -113,6 +136,11 @@ export class InputEditor implements IEditor {
113136 if ( referencePosition ?. rect ) {
114137 this . adjustPosition ( referencePosition . rect ) ;
115138 }
139+ } else {
140+ if ( ! container . contains ( this . element ) ) {
141+ this . element . parentElement . removeChild ( this . element ) ;
142+ this . container . appendChild ( this . element ) ;
143+ }
116144 }
117145 if ( value !== undefined && value !== null ) {
118146 this . setValue ( value ) ;
@@ -144,10 +172,35 @@ export class InputEditor implements IEditor {
144172
145173 onEnd ( ) {
146174 // do nothing
147- if ( this . container ?. contains ( this . element ) ) {
148- this . container . removeChild ( this . element ) ;
149- this . element = undefined ;
175+ if ( ! this . element ) {
176+ return ;
177+ }
178+
179+ // 保存元素引用,避免在移除过程中被其他代码修改
180+ const element = this . element ;
181+
182+ // 先移除所有事件监听器,避免在 removeChild 时触发 blur 等事件
183+ this . eventHandlers . forEach ( ( { type, handler } ) => {
184+ element . removeEventListener ( type , handler ) ;
185+ } ) ;
186+ this . eventHandlers = [ ] ;
187+
188+ // 检查元素的父节点是否存在,确保元素还在 DOM 中
189+ const parentNode = element . parentNode ;
190+ if ( parentNode ) {
191+ try {
192+ // 事件监听器已经移除,可以安全地移除元素,不会触发 blur 等事件
193+ parentNode . removeChild ( element ) ;
194+ } catch ( error ) {
195+ // 如果元素已经被移除或移动,忽略 NotFoundError
196+ if ( error instanceof Error && error . name !== 'NotFoundError' ) {
197+ throw error ;
198+ }
199+ }
150200 }
201+
202+ // 清空引用
203+ this . element = undefined ;
151204 }
152205
153206 isEditorElement ( target : HTMLElement ) {
0 commit comments