Skip to content

Commit a16f982

Browse files
author
weilei
committed
refactor: 优化拖拽样式切换逻辑,增加动画效果并移除防抖处理
1 parent 088c96b commit a16f982

File tree

1 file changed

+142
-60
lines changed
  • packages/element-x-ui/src/components/Attachments/src

1 file changed

+142
-60
lines changed

packages/element-x-ui/src/components/Attachments/src/main.vue

Lines changed: 142 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -278,29 +278,7 @@ export default {
278278
}, wait)
279279
}
280280
},
281-
// 上传相关方法
282-
toggleDragStyle(isDrag) {
283-
this.isTargetDrag = isDrag
284-
if (this.targetElement) {
285-
const isBodyTarget = this.targetElement === document.body // 判断是否为body
286281
287-
if (isDrag) {
288-
// 针对body特殊处理
289-
if (isBodyTarget && this.$refs.dropAreaRef) {
290-
this.$refs.dropAreaRef.style.position = 'fixed'
291-
this.$refs.dropAreaRef.style.width = '100vw'
292-
this.$refs.dropAreaRef.style.height = '100vh'
293-
this.$refs.dropAreaRef.style.left = '0'
294-
this.$refs.dropAreaRef.style.top = '0'
295-
} else {
296-
// 其他元素保持原逻辑
297-
this.targetElement.style.position = 'relative'
298-
}
299-
} else {
300-
this.targetElement.style.position = ''
301-
}
302-
}
303-
},
304282
customUpload(options) {
305283
// 自定义上传方法,如果父组件提供了http-request,则使用父组件的
306284
if (this.$attrs['http-request']) {
@@ -328,6 +306,7 @@ export default {
328306
handleUploadError(error, file, fileList) {
329307
this.$emit('uploadError', error, file, fileList)
330308
},
309+
331310
getTargetElement() {
332311
if (!this.dragTarget) return this.$refs.wrapperRef
333312
@@ -348,22 +327,75 @@ export default {
348327
// 兜底返回 wrapperRef
349328
return this.$refs.wrapperRef
350329
},
330+
// 修改拖拽样式切换方法
331+
toggleDragStyle(isDrag) {
332+
console.log('toggleDragStyle called:', isDrag) // 调试用,可以删除
333+
334+
this.isTargetDrag = isDrag
335+
336+
if (this.targetElement) {
337+
const isBodyTarget = this.targetElement === document.body
338+
339+
if (isDrag) {
340+
// 立即显示拖拽区域
341+
this.$nextTick(() => {
342+
this.appendDragArea()
343+
})
344+
345+
if (isBodyTarget && this.$refs.dropAreaRef) {
346+
this.$refs.dropAreaRef.style.position = 'fixed'
347+
this.$refs.dropAreaRef.style.width = '100vw'
348+
this.$refs.dropAreaRef.style.height = '100vh'
349+
this.$refs.dropAreaRef.style.left = '0'
350+
this.$refs.dropAreaRef.style.top = '0'
351+
this.$refs.dropAreaRef.style.zIndex = '9999'
352+
} else {
353+
this.targetElement.style.position = 'relative'
354+
}
355+
} else {
356+
// 延迟移除拖拽区域,避免闪烁
357+
setTimeout(() => {
358+
this.removeDragArea()
359+
}, 100)
360+
361+
if (!isBodyTarget) {
362+
this.targetElement.style.position = ''
363+
}
364+
}
365+
}
366+
},
367+
// 修改事件处理方法
351368
targetDragEnter(event) {
352369
event.preventDefault()
353-
this.debouncedToggleStyle(true)
370+
event.stopPropagation()
371+
372+
// 移除防抖,直接执行
373+
this.toggleDragStyle(true)
354374
},
355375
targetDropLeave(event) {
356376
event.preventDefault()
357-
// 新增逻辑:若离开后进入的元素仍在目标元素内部,不执行样式移除
377+
event.stopPropagation()
378+
358379
const relatedTarget = event.relatedTarget
359-
if (this.targetElement && this.targetElement.contains(relatedTarget)) {
380+
381+
// 如果离开后进入的元素仍在目标元素内部,或者进入了拖拽区域本身,不执行样式移除
382+
if (
383+
this.targetElement &&
384+
(this.targetElement.contains(relatedTarget) || (this.$refs.dropAreaRef && this.$refs.dropAreaRef.contains(relatedTarget)))
385+
) {
360386
return
361387
}
362-
this.debouncedToggleStyle(false)
388+
389+
// 移除防抖,直接执行
390+
this.toggleDragStyle(false)
363391
},
364392
targetDrop(event) {
365393
event.preventDefault()
366-
this.debouncedToggleStyle(false)
394+
event.stopPropagation()
395+
396+
// 立即移除拖拽样式
397+
this.toggleDragStyle(false)
398+
367399
if (event.dataTransfer) {
368400
const files = event.dataTransfer.files
369401
if (files.length) {
@@ -377,33 +409,58 @@ export default {
377409
},
378410
targetDragOver(event) {
379411
event.preventDefault()
412+
event.stopPropagation()
380413
},
381414
// 卡片相关方法
382415
handleDelete(item, index) {
383416
this.$emit('delete-card', item, index)
384417
this.$nextTick(() => this.debouncedCheckPing())
385418
},
386-
// Vue2 中实现类似 teleport 的功能
419+
// 修改 DOM 操作方法
387420
appendDragArea() {
388-
if (this.$refs.dropAreaRef && this.targetElement) {
389-
// 确保 dropAreaContainer 已渲染
390-
this.$nextTick(() => {
421+
if (!this.$refs.dropAreaRef || !this.targetElement) {
422+
return
423+
}
424+
425+
// 确保元素已经渲染
426+
this.$nextTick(() => {
427+
const dragAreaNode = this.$refs.dropAreaRef
428+
429+
// 检查是否已经添加过了
430+
if (dragAreaNode.parentNode !== this.targetElement) {
431+
// 显示容器
391432
if (this.$refs.dropAreaContainer) {
392-
const dragAreaNode = this.$refs.dropAreaRef
393-
this.targetElement.appendChild(dragAreaNode)
433+
this.$refs.dropAreaContainer.style.display = 'block'
394434
}
395-
})
396-
}
435+
436+
// 添加到目标元素
437+
this.targetElement.appendChild(dragAreaNode)
438+
439+
// 强制重绘
440+
dragAreaNode.offsetHeight
441+
}
442+
})
397443
},
398444
removeDragArea() {
399-
if (this.$refs.dropAreaRef && this.targetElement && this.$refs.dropAreaRef.parentNode === this.targetElement) {
400-
this.targetElement.removeChild(this.$refs.dropAreaRef)
445+
if (!this.$refs.dropAreaRef || !this.targetElement) {
446+
return
447+
}
448+
449+
const dragAreaNode = this.$refs.dropAreaRef
450+
451+
if (dragAreaNode.parentNode === this.targetElement) {
452+
this.targetElement.removeChild(dragAreaNode)
453+
}
454+
455+
// 隐藏容器
456+
if (this.$refs.dropAreaContainer) {
457+
this.$refs.dropAreaContainer.style.display = 'none'
401458
}
402459
},
403460
},
404461
created() {
405462
this.debouncedCheckPing = this.debounce(this.checkPing, 100)
406-
this.debouncedToggleStyle = this.debounce(this.toggleDragStyle, 100)
463+
// this.debouncedToggleStyle = this.debounce(this.toggleDragStyle, 100)
407464
},
408465
}
409466
</script>
@@ -588,33 +645,58 @@ export default {
588645
589646
/* 设置拖放区域的样式 */
590647
&-drop-area {
591-
position: absolute;
592-
top: 0;
593-
left: 0;
594-
width: calc(100% - 4px);
595-
height: calc(100% - 4px);
596-
border-radius: 15px;
597-
border: 2px dashed $--color-primary;
598-
z-index: 9999;
599-
display: flex;
600-
align-items: center;
601-
justify-content: center;
602-
flex-direction: column;
603-
background: rgba(225, 225, 225, 0.3);
604-
backdrop-filter: blur(2px);
648+
position: absolute !important;
649+
top: 0 !important;
650+
left: 0 !important;
651+
width: calc(100% - 4px) !important;
652+
height: calc(100% - 4px) !important;
653+
border-radius: 15px !important;
654+
border: 2px dashed $--color-primary !important;
655+
z-index: 9999 !important;
656+
display: flex !important;
657+
align-items: center !important;
658+
justify-content: center !important;
659+
flex-direction: column !important;
660+
background: rgba(225, 225, 225, 0.8) !important; // 增加透明度
661+
backdrop-filter: blur(4px) !important; // 增加模糊效果
662+
animation: dragAreaShow 0.3s ease-in-out !important; // 添加显示动画
663+
pointer-events: none !important; // 防止拖拽区域本身阻止事件
605664
606665
&-icon {
607-
font-size: 50px;
608-
color: $--color-primary;
666+
font-size: 50px !important;
667+
color: $--color-primary !important;
668+
animation: bounce 1s infinite alternate !important; // 添加跳动动画
609669
}
610670
611671
&-text {
612-
font-size: 16px;
613-
color: $--color-primary;
614-
margin-top: 10px;
615-
text-align: center;
616-
width: 100%;
617-
max-width: 300px;
672+
font-size: 16px !important;
673+
color: $--color-primary !important;
674+
margin-top: 10px !important;
675+
text-align: center !important;
676+
width: 100% !important;
677+
max-width: 300px !important;
678+
font-weight: bold !important;
679+
}
680+
}
681+
682+
// 添加动画关键帧
683+
@keyframes dragAreaShow {
684+
from {
685+
opacity: 0;
686+
transform: scale(0.9);
687+
}
688+
to {
689+
opacity: 1;
690+
transform: scale(1);
691+
}
692+
}
693+
694+
@keyframes bounce {
695+
from {
696+
transform: translateY(0);
697+
}
698+
to {
699+
transform: translateY(-10px);
618700
}
619701
}
620702
}

0 commit comments

Comments
 (0)