Antd 下拉面板的位置计算错误

news2024/11/25 4:36:18

项目场景:

公司使用无界微前端集成ERP项目应用(可惜没跟着走一边无界,难受),某些子应用使用时,发现antd的弹窗弹出的位置不对。如下图:
在这里插入图片描述


问题描述

无界微前端嵌入的子应用中的antd的下拉框位置计算不正确。

无界常见问题有类似的有关问题,说是子应用的body标签增加position:relative即可

使用了此方法,倒是解决了某些子应用的同类情况,但是还有一些并没有生效。


解决方案:

方案一

先是排查了antd相关位置计算的源码,发现位置的计算是基于dom-align实现的,阅读到了最后的相关方法。
方法的算法计算没有细看,经过控制台的debugger,发现是出现错误的下拉框自适应弹窗的计算的方法没有走。

自适应弹窗的计算依赖于:窗口可视区域、target区域(select框)、origin区域(下拉面板)三部分的位置做计算。因为无界微前端的模式可能导致了未知的尺寸的错误计算。使得最后一行没有执行自适应的代码。

通过代码的阅读,发现参数alwaysByViewport可以控制始终重计算自适应弹窗,因此就有了第一个解决方案,把这个参数置为true。

继续阅读antd源码,发现他并没有抛出这个属性,因此需要我们重写一下。
在这里插入图片描述
下列代码块为重写的方法(其实就是多加了一个属性)和dom-align计算的源码

export function transPlacement2DropdownAlign(direction, placement) {
  let overflow = {
    adjustX: 1,
    adjustY: 1,
    alwaysByViewport: true, // 始终允许自适应
  };
  switch (placement) {
    case 'bottomLeft': {
      return {
        points: ['tl', 'bl'],
        offset: [0, 4],
        overflow: overflow,
      };
    }
    case 'bottomRight': {
      return {
        points: ['tr', 'br'],
        offset: [0, 4],
        overflow: overflow,
      };
    }
    case 'topLeft': {
      return {
        points: ['bl', 'tl'],
        offset: [0, -4],
        overflow: overflow,
      };
    }
    case 'topRight': {
      return {
        points: ['br', 'tr'],
        offset: [0, -4],
        overflow: overflow,
      };
    }
    default: {
      return {
        points: direction === 'rtl' ? ['tr', 'br'] : ['tl', 'bl'],
        offset: [0, 4],
        overflow: overflow,
      };
    }
  }
}
/**
 * 获得元素的显示部分的区域
 */
function getVisibleRectForElement(element, alwaysByViewport) {
  var visibleRect = {
    left: 0,
    right: Infinity,
    top: 0,
    bottom: Infinity
  };
  var el = getOffsetParent(element);
  var doc = utils.getDocument(element);
  var win = doc.defaultView || doc.parentWindow;
  var body = doc.body;
  var documentElement = doc.documentElement;

  // Determine the size of the visible rect by climbing the dom accounting for
  // all scrollable containers.
  while (el) {
    // clientWidth is zero for inline block elements in ie.
    if ((navigator.userAgent.indexOf('MSIE') === -1 || el.clientWidth !== 0) &&
    // body may have overflow set on it, yet we still get the entire
    // viewport. In some browsers, el.offsetParent may be
    // document.documentElement, so check for that too.
    el !== body && el !== documentElement && utils.css(el, 'overflow') !== 'visible') {
      var pos = utils.offset(el);
      // add border
      pos.left += el.clientLeft;
      pos.top += el.clientTop;
      visibleRect.top = Math.max(visibleRect.top, pos.top);
      visibleRect.right = Math.min(visibleRect.right,
      // consider area without scrollBar
      pos.left + el.clientWidth);
      visibleRect.bottom = Math.min(visibleRect.bottom, pos.top + el.clientHeight);
      visibleRect.left = Math.max(visibleRect.left, pos.left);
    } else if (el === body || el === documentElement) {
      break;
    }
    el = getOffsetParent(el);
  }

  // Set element position to fixed
  // make sure absolute element itself don't affect it's visible area
  // https://github.com/ant-design/ant-design/issues/7601
  var originalPosition = null;
  if (!utils.isWindow(element) && element.nodeType !== 9) {
    originalPosition = element.style.position;
    var position = utils.css(element, 'position');
    if (position === 'absolute') {
      element.style.position = 'fixed';
    }
  }
  var scrollX = utils.getWindowScrollLeft(win);
  var scrollY = utils.getWindowScrollTop(win);
  var viewportWidth = utils.viewportWidth(win);
  var viewportHeight = utils.viewportHeight(win);
  var documentWidth = documentElement.scrollWidth;
  var documentHeight = documentElement.scrollHeight;

  // scrollXXX on html is sync with body which means overflow: hidden on body gets wrong scrollXXX.
  // We should cut this ourself.
  var bodyStyle = window.getComputedStyle(body);
  if (bodyStyle.overflowX === 'hidden') {
    documentWidth = win.innerWidth;
  }
  if (bodyStyle.overflowY === 'hidden') {
    documentHeight = win.innerHeight;
  }

  // Reset element position after calculate the visible area
  if (element.style) {
    element.style.position = originalPosition;
  }
  if (alwaysByViewport || isAncestorFixed(element)) {
    // Clip by viewport's size.
    visibleRect.left = Math.max(visibleRect.left, scrollX);
    visibleRect.top = Math.max(visibleRect.top, scrollY);
    visibleRect.right = Math.min(visibleRect.right, scrollX + viewportWidth);
    visibleRect.bottom = Math.min(visibleRect.bottom, scrollY + viewportHeight);
  } else {
    // Clip by document's size.
    var maxVisibleWidth = Math.max(documentWidth, scrollX + viewportWidth);
    visibleRect.right = Math.min(visibleRect.right, maxVisibleWidth);
    var maxVisibleHeight = Math.max(documentHeight, scrollY + viewportHeight);
    visibleRect.bottom = Math.min(visibleRect.bottom, maxVisibleHeight);
  }
  return visibleRect.top >= 0 && visibleRect.left >= 0 && visibleRect.bottom > visibleRect.top && visibleRect.right > visibleRect.left ? visibleRect : null;
}

方案二

究其原因,是窗口可视区域、target区域(select框)、origin区域(下拉面板)三部分的位置做计算。因为无界微前端的模式可能导致了未知的尺寸的错误计算。使得最后一行没有执行自适应的代码。
因此,我尝试将子应用的高度变成100vh。发现也可以解决问题,但是这样导致了一些其他未知的错误,比如挡住了菜单,antd的弹窗出现问题。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/552457.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【谷粒商城笔记】基于docker的mysql、redis环境配置

0.系统 宝塔 v7.5.1 Centos v8.2 1. 安装Docker 直接yum install docker会提示找不到 > docker-client-latest \ docker-common \ docker-latest \ docker-latest-logrotate \ docker-logrotate \ docker-engine Loaded plugins: fastestmirror No Match for argument: …

Prometheus如何优化远程读写的性能

Prometheus如何优化远程读写的性能 场景 为了解决prometheus本地存储带来的单点问题,我们一般在高可用监控架构中会使用远程存储,并通过配置prometheus的remote_write和remote_read来对接 远程写优化:remote_write 用户可以在Prometheus配…

码上行动:零基础学会Python编程(文末送书)

🤵‍♂️ 个人主页:艾派森的个人主页 ✍🏻作者简介:Python学习者 🐋 希望大家多多支持,我们一起进步!😄 如果文章对你有帮助的话, 欢迎评论 💬点赞&#x1f4…

Day3 字符串中找出连续最长的数字串、数组中出现次数超过一半的数字

✨个人主页: 北 海 🎉所属专栏: C/C相关题解 🎃操作环境: Visual Studio 2019 版本 16.11.17 文章目录 选择题1、进程管理2、计算机组成原理 编程题1、字符串中找出连续最长的数字串2、数组中出现次数超过一半的数字 选…

和数组处理有关的一些OJ题;ArrayList 实现简单的洗牌算法(JAVA)(ArrayList)

接上次博客:数据结构初阶(2)(ArrayList简介、ArrayList()的构造方法、ArrayList的扩容、方法和三种遍历方法、ArrayList实现杨辉三角、ArrayList 的优缺点)_di-Dora的博客-CSDN博客 1、给你一个数组 nums 和一个值 va…

FreeRTOS(6)----软件定时器

一,软件定时器概述 软件定时器允许设置一段时间,当设定的时间到达之后就会执行指定的功能函数,被定时器调用的这个函数叫做定时器的回调函数。回调函数的两次执行间隔叫做定时器的定时周期。 二,回调函数的注意事项 回调函数是…

Linux文件权限管理

1、Linux权限介绍 权限管理,其实就是指对不同的用户,设置不同的文件访问权限。 Linux 系统,最常见的文件权限有 3 种,即对文件的读(用 r 表示)、写(用 w 表示)和执行(用…

github.io创建个人网站

文章目录 github.io介绍使用步骤新建仓库添加文件 github.io介绍 github.io是 GitHub 提供的免费 Pages服务,不需要购买云服务器和域名,就可以将自己的项目、博客在互联网上进行共享。 使用步骤 新建仓库 创建一个新的仓库,仓库名设置为如…

Nacos环境隔离

随着Nacos 0.8版本的release,Nacos离正式生产版本又近了一步(其实已经有不少企业已经上了生产,如虎牙)。一般而言,企业研发的流程一般是这样的:先在测试环境开发和测试功能,然后再灰度&#xff…

CANFDCAN协议对比 - 基础介绍_01

目录 一、为什么会出现CANFD? 1、信号数量大量增加 2、新要求,新总线系统 3、CAN性能限制 4、更短的位时间也能满足 ???CAN是否会被取代? 二、CANFD优点 1、更多数据,更低总线负载率 2…

计算机网络 三(数据链路层)下

流量控制与可靠传输机制 流量控制手段:接收方收不下就不回复确认。 传输层流量控制手段:接收端给发送端一个窗口公告 #可用协议 可用协议 停止等待协议 概念、出现原因 停止等待协议是一种简单的数据传输协议,常用于数据传输的可靠性较低…

【Docker实战】使用Docker部署Tomcat

【Docker实战】使用Docker部署Tomcat 一、Tomcat介绍1. Tomcat简介2. Tomcat特点3. Tomcat容器部署的优点4. Tomcat的配置文件 二、检查本地环境三、检查本地Docker环境1. 检查本地Docker服务2. 检查Docker版本 四、搜索docker hub中的tomcat镜像五、下载tomcat镜像六、创建Tom…

chatgpt赋能Python-pythona的三次方

Python 的三次方:探索 Python 强大的数学计算能力 Python 是一种高级编程语言,被广泛应用于数据分析、机器学习、人工智能等领域。除此之外,Python 还拥有强大的数学计算能力,其中包括 Python 的三次方计算功能。在本文中&#x…

AI人工智能标记数据的技术:类型、方法、质量控制、应用

AI人工智能 标记数据 在人工智能(Artificial Intelligence,简称AI)领域中,标记数据是非常重要的一环。它是指对原始数据进行标记和注释,以便机器学习算法可以理解和利用这些数据。标记数据可以提高机器学习模型的准确…

实战【云原生】--- Kubernetes集群

K8S集群负载均衡层防火墙 实例 一、kubeadm 部署 K8S 集群架构1、关闭所有节点的防火墙 核心防护 iptables swap交换2、修改主机名3、调整内核参数 二、安装Docker1、所有节点安装docker2、所有节点配置k8s源3、所有节点安装kubeadm,kubelet和kubectl 三、部署k8s集…

2023/5/21总结

因为之前高中学过一点点的html。虽然不是很多&#xff0c;但是有一点点基础&#xff0c;看了一些关于html的知识点&#xff0c;算是复习了&#xff0c;如果后面忘记打算再去查。 html是超文本标记语言&#xff0c;通常由<></>构成&#xff0c;当然也有单标记&…

chatgpt赋能Python-python5__2

Python中整除运算符 // 的用法和重要性 在Python中&#xff0c;整除运算符 // 有着广泛的应用&#xff0c;特别是在数据分析、科学计算、金融量化、游戏开发等领域中&#xff0c;它是很重要的基础运算符。 什么是整除运算符 //&#xff1f; 整除运算符 // 是Python中的一种二…

chatgpt赋能Python-pythonbmi

Python计算BMI - 计算和判断你的身体状况 BMI&#xff0c;即Body Mass Index&#xff0c;中文翻译为“身体质量指数”&#xff0c;是目前世界上公认的反映体重是否正常的最权威的指标之一。 计算BMI可以帮助我们判断自己的身体状况&#xff0c;是如今非常流行的健康指标之一。…

【iOS】SDWebImage源码学习--未完

SDWebImage的主要功能及相关知识点 SDWebImage是一个流行的第三方库&#xff0c;用于在iOS和macOS应用程序中异步下载和缓存图像。它提供了一种简单而强大的方式来处理网络图像加载和缓存&#xff0c;具有以下主要功能&#xff1a; 异步下载&#xff1a;SDWebImage使用多线程…

MyBatis中动态SQL的使用和注意事项说明

文章目录 0、前言1、if2、where3、trim4、choose-when-otherwise5、foreach应用场景1&#xff1a; 通过数组实现批量删除应用场景2&#xff1a; 通过list集合实现批量添加 6、include抽取公共SQL片段 0、前言 MyBatis框架动态SQL技术是根据特定的条件拼接SQL语句的功能&#x…