vue3 根据点击位置,实现一个用户头像弹框定位

vue3 根据点击位置,实现一个用户头像弹框定位

需求背景

最近在做直播后台,涉及到对用户的一些操作,比如关注/取关/禁言/踢出直播间。多个地方都要用,需要封装一个弹框组件

效果图

实现过程分析

  1. 根据点击元素,获取元素的位置
  2. 动态设置元素top,left位置

top 和 left 如何获取

根据 点击事件event参数,来获取位置,根据需要来实际计算位置

  • 元素距离左边的距离 + 元素本身的宽度

获取元素top/left,其实直接用getBoundingClientRect 里的bottom / right 即可

代码实现

js 复制代码
export const getCurrentDialogXY = (event: Event) => {
  const target = event.target as HTMLElement
  const { bottom, right } = target.getBoundingClientRect()
  return { bottom, right }
}

调用

scss 复制代码
```js
const avatarHandler = (event: Event) => {
  const { right, bottom } = getCurrentDialogXY(event)
  currentX.value = right
  currentY.value = bottom
}

传入子组件,在子组件内接收到left/top 重新定位即可

js 复制代码
    <user-info-dialog
        :left="currentX"
        :top="currentY"
    />
js 复制代码
<div ref="userInfoRef" class="dialog-wrap" :style="{ top: top + 'px', left: left + 'px' }"></div>

细节处理

  1. 通过设置,你会发现弹框始终定位在元素右下角,可以根据自身需求,设置元素位置

通过监听弹框的ref(弹框有显示隐藏逻辑,所以监听弹框的ref即可,然后动态设置位置),

js 复制代码
watchEffect(() => {
  const userInfoRefValue = userInfoRef.value
  if (userInfoRefValue) {
    const offsetHeight = userInfoRefValue.offsetHeight // 获取弹框的高度
    const offsetWidth = userInfoRefValue.offsetWidth // 获取元素的宽度

    // 不管弹框显示是左侧还是右侧,根据需求 都需要 减去 弹框的高度 - 用户头像高度的一半 进行定位
      propTop.value = props.top - offsetHeight - userAvatarWidth.value / 2
      
    // 如果是弹框显示在左侧,需要减去弹框的宽度 - 头像的宽度
    if (props.roleEnumType === 1) {
      propLeft.value = props.left - offsetWidth - userAvatarWidth.value
    }
  }
})
  1. 弹框打开之后,要点击所有位置,都可以关闭
  • 那我们就需要实现一个朦层(透明色),点击朦层,触发关闭即可

你会发现,其实我们的整个元素,是直接在根节点上,根常规里的,每个弹框,必须要绑定在循环里,才能做一一对应的关系,怎么不太一样呢? 这里是用到的

vue3中的Teleport:将其插槽内容渲染到 DOM 中的另一个位置 这对于我们层级比较多,做全局定位,脱离当前元素,非常好用!!!

当我们触发关闭事件,抛出去让父组件处理即可

相关推荐
Flynt2 小时前
axios 被投毒半年后,我把 npm 的"安全防线"实测了一遍:最信任的 SHA512 是安慰剂
前端·npm·node.js
excel3 小时前
Base62 和 Base64 有什么区别?
前端
风骏时光牛马4 小时前
大模型底层架构与AI源码深度剖析
前端
掘金挖土5 小时前
前端手摸手跑路之 AI 应用开发(九)
前端·后端
中文呀7 小时前
三维 GIS 离线缓存实战:逆向 CesiumOfflineCache,并亲手为它补上"自动更新"能力
前端
前进前进前进8 小时前
TRAE 全链路实战:做了一个警示牌一键生成器:纯 Canvas、单文件、零依赖
前端
小万7429 小时前
God‘s Eye View 深度解析:15 路公开信号 + CesiumJS 的浏览器级 OSINT 控制台,60 帧渲染的“真实间谍卫星模拟器”
前端
IT星宿9 小时前
浏览器标签页全是一个图标:我用名字哈希生成 favicon,让每个项目都有身份标识
前端
全栈项目管理程序猿9 小时前
ArcGIS JS 基础教程(32):体元系列 - VoxelSlice 体元切片
前端·javascript