1
This commit is contained in:
@@ -94,29 +94,50 @@ export default {
|
|||||||
methods: {
|
methods: {
|
||||||
show(callback) {
|
show(callback) {
|
||||||
this.ensureParentPosition()
|
this.ensureParentPosition()
|
||||||
|
// 使用 requestAnimationFrame 确保在下一帧渲染时显示,避免闪烁
|
||||||
|
requestAnimationFrame(() => {
|
||||||
this.showPanel = true
|
this.showPanel = true
|
||||||
this.callback = callback
|
this.callback = callback
|
||||||
|
})
|
||||||
},
|
},
|
||||||
hide() {
|
hide() {
|
||||||
this.showPanel = false
|
this.showPanel = false
|
||||||
this.callback = null
|
this.callback = null
|
||||||
|
// 延迟恢复父容器定位,等待动画完成
|
||||||
|
setTimeout(() => {
|
||||||
this.restoreParentPosition()
|
this.restoreParentPosition()
|
||||||
|
}, 300)
|
||||||
},
|
},
|
||||||
ensureParentPosition() {
|
ensureParentPosition() {
|
||||||
// 确保父容器有 position: relative
|
// 确保父容器有 position: relative,提前设置避免闪烁
|
||||||
|
if (!this.parentElement) {
|
||||||
|
// 在组件挂载后立即获取父元素
|
||||||
|
if (this.$el && this.$el.parentElement) {
|
||||||
|
this.parentElement = this.$el.parentElement
|
||||||
|
} else {
|
||||||
|
// 如果组件还未挂载,使用 $nextTick
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
if (!this.parentElement && this.$el) {
|
if (this.$el && this.$el.parentElement) {
|
||||||
this.parentElement = this.$el.parentElement
|
this.parentElement = this.$el.parentElement
|
||||||
}
|
}
|
||||||
|
this.setParentPosition()
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.setParentPosition()
|
||||||
|
},
|
||||||
|
setParentPosition() {
|
||||||
if (this.parentElement) {
|
if (this.parentElement) {
|
||||||
const computedStyle = window.getComputedStyle(this.parentElement)
|
const computedStyle = window.getComputedStyle(this.parentElement)
|
||||||
const position = computedStyle.position
|
const position = computedStyle.position
|
||||||
if (position === 'static' || !position) {
|
if (position === 'static' || !position) {
|
||||||
this.originalParentPosition = this.parentElement.style.position || ''
|
this.originalParentPosition = this.parentElement.style.position || ''
|
||||||
|
// 使用 will-change 优化性能
|
||||||
|
this.parentElement.style.willChange = 'transform'
|
||||||
this.parentElement.style.position = 'relative'
|
this.parentElement.style.position = 'relative'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
|
||||||
},
|
},
|
||||||
restoreParentPosition() {
|
restoreParentPosition() {
|
||||||
// 恢复父容器的原始定位
|
// 恢复父容器的原始定位
|
||||||
@@ -126,6 +147,7 @@ export default {
|
|||||||
} else {
|
} else {
|
||||||
this.parentElement.style.position = ''
|
this.parentElement.style.position = ''
|
||||||
}
|
}
|
||||||
|
this.parentElement.style.willChange = ''
|
||||||
this.originalParentPosition = null
|
this.originalParentPosition = null
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -150,14 +172,25 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
mounted() {
|
||||||
|
// 组件挂载后立即获取父元素并设置定位,避免后续闪烁
|
||||||
|
this.$nextTick(() => {
|
||||||
|
if (this.$el && this.$el.parentElement) {
|
||||||
|
this.parentElement = this.$el.parentElement
|
||||||
|
// 预先设置 position,避免显示时闪烁
|
||||||
|
this.setParentPosition()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
beforeDestroy() {
|
beforeDestroy() {
|
||||||
// 组件销毁时关闭面板并清理
|
// 组件销毁时关闭面板并清理
|
||||||
if (this.showPanel) {
|
if (this.showPanel) {
|
||||||
this.hide()
|
this.hide()
|
||||||
}
|
} else {
|
||||||
this.restoreParentPosition()
|
this.restoreParentPosition()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
@@ -170,6 +203,11 @@ export default {
|
|||||||
z-index: 1000;
|
z-index: 1000;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
/* 使用 will-change 优化性能,避免重排 */
|
||||||
|
will-change: transform;
|
||||||
|
/* 使用 transform 代替 position,避免触发重排 */
|
||||||
|
transform: translateZ(0);
|
||||||
|
backface-visibility: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.float-panel {
|
.float-panel {
|
||||||
@@ -182,6 +220,10 @@ export default {
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
/* 使用 GPU 加速,避免闪烁 */
|
||||||
|
will-change: transform;
|
||||||
|
transform: translateZ(0);
|
||||||
|
backface-visibility: hidden;
|
||||||
|
|
||||||
&.float-panel-right {
|
&.float-panel-right {
|
||||||
animation: slideInRight 0.3s ease-out;
|
animation: slideInRight 0.3s ease-out;
|
||||||
@@ -242,12 +284,16 @@ export default {
|
|||||||
// 动画效果
|
// 动画效果
|
||||||
.float-panel-enter-active,
|
.float-panel-enter-active,
|
||||||
.float-panel-leave-active {
|
.float-panel-leave-active {
|
||||||
transition: opacity 0.3s;
|
transition: opacity 0.3s ease;
|
||||||
|
/* 使用 transform 代替 opacity,性能更好 */
|
||||||
|
will-change: transform, opacity;
|
||||||
}
|
}
|
||||||
|
|
||||||
.float-panel-enter,
|
.float-panel-enter,
|
||||||
.float-panel-leave-to {
|
.float-panel-leave-to {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
|
/* 使用 transform 避免重排 */
|
||||||
|
transform: translateZ(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes slideInRight {
|
@keyframes slideInRight {
|
||||||
|
|||||||
Reference in New Issue
Block a user