【React】antd popover定位不准闪跳解决+自己实现popover库

前言

  • 我在写H5-dooring时,发现我们用的popover会发生闪跳,而且第一次闪跳就算了,每次还会有另一个方向的闪跳。
  • 于是我大概百度了下,基本都说需要给固定宽高即可,让后试了下发现没用,就算触发组件和弹窗元素都给了宽高,也一样闪跳。
  • 由于antd的popover套别人的库,别人的又套别人的,别人的再套别人的,所以我懒得翻了,直接自己写一个。

初步实现

  • 首先,我对popover粗略进行实现,主要就是一个弹窗定位问题,然后我照我预想实现后发现,一样会出现闪跳,但只有第一次会闪跳,后面比较正常:

在这里插入图片描述

  • 可以看见,第一次显示会在左边,后续显示位置都ok。
  • 所以思路就是让其在第一次显示时进行处理,顺便实现动画效果,不至于出现那么突兀。
  • 由于我想做一个除react外零依赖的,所以就不考虑react-transition-group或者styledcomponent,直接进行手撸动画。

实现思路

  • 其中第一次漂移问题直接使用动画解决,将opacity置为0即可。
@keyframes yhmodalopenanimate{
    0%{
        opacity: 0;
    }
    100%{
        opacity: 1;
    }
}
@keyframes yhmodalcloseanimate{
    0%{
        opacity:1;
    }

    100%{
        opacity: 0;
    }
}

.yhmodalopen{
    animation: yhmodalopenanimate 0.15s ease-in;
}

.yhmodalclose{
    animation: yhmodalcloseanimate 0.15s ease-in;
}
  • 在实现过程中发现,如果元素(也就是包裹的元素加上弹窗的元素)形变或者有那种改变外形的动画,会导致定位不正确,我进行计算位置时需要拿到2者的dom的。
  • 另外,需要暴露出强制刷新方法,在某些情况下需要刷新函数,比如监听windows的resize事件,这样位置变化后,再点击,就不会出现到原来的位置了。
	useEffect(() => {
		if (callback) {
			callback(() => forceRender((v) => v + 1));
		}
	}, [callback]);

	useEffect(() => {
		const handler = () => {
			forceRender((prev) => prev + 1);
		};
		window.addEventListener("resize", handler);
		return () => {
			window.removeEventListener("resize", handler);
		};
	}, [forceRender]);
  • 还有个监听事件的问题,这里我暴露参数,让用户判断是否需要点击Modal外进行关闭。
  • 剩下的都是体力活,算位置即可:
export type PopDirections =
	| "TL"
	| "TOP"
	| "TR"
	| "LT"
	| "LEFT"
	| "LB"
	| "BL"
	| "BOTTOM"
	| "BR"
	| "RT"
	| "RIGHT"
	| "RB";

export function switchPosition(
	sign: PopDirections,
	modalrect: DOMRect,
	popconfirmrect: DOMRect,
	scroll: number
): CSSProperties {
	let triangle = 8;
	switch (sign) {
		case "TL":
			return {
				top: popconfirmrect.top + scroll - modalrect.height - triangle,
				left: popconfirmrect.left,
			};
		case "TOP":
		....
		case "TR":
		....
.........
	}
}

效果

在这里插入图片描述

npm i yh-react-popover
  • 右下角的添加按钮还需要绑定右边的监听scroll进行强刷,否则右边进行滚动后,popover不会随着滚动移动。可以参考h5dooring中的实现。
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
### 回答1: 可以使用Antd中的Popover组件,来循环渲染内容。例如:const list = [{name: '张三', age: 18}, {name: '李四', age: 21}];return ( <Popover content={ list.map((item, index) => { return <p key={index}>{item.name} - {item.age}</p> }) }> <Button>点击显示内容</Button> </Popover> ); ### 回答2: 在React Antd中,可以通过使用map函数来循环生成Popover组件的content内容。以下是一个示例代码: ```jsx import React from 'react'; import { Popover, Button } from 'antd'; const contentData = ['内容1', '内容2', '内容3']; const ExampleComponent = () => { return ( <div> {contentData.map((content, index) => ( <Popover key={index} content={content} title={`标题${index+1}`} > <Button type="primary">按钮{index+1}</Button> </Popover> ))} </div> ); }; export default ExampleComponent; ``` 上面的代码中,首先定义了一个contentData数组,存储了要循环生成的内容。然后在ExampleComponent组件中,通过map函数循环contentData数组,为每个内容生成一个Popover组件,并将对应的内容传递给content属性。通过设置不同的标题和按钮,可以根据需求自定义样式和布局。 最后,将生成的Popover组件渲染到页面上。每个Popover组件都包括一个按钮,当鼠标悬停在按钮上时,会显示对应的内容和标题。 这样,就实现了循环生成Popover组件的content内容。 ### 回答3: 在React Antd中,我们可以使用循环来动态生成Popover组件的content属性内容。具体代码如下: ```jsx import React from 'react'; import { Popover, Button } from 'antd'; const contentArray = ['内容1', '内容2', '内容3']; // 假设要循环生成的内容数组 const PopoverWithLoopContent = () => { return ( <Popover content={( <div> {contentArray.map((content, index) => ( <p key={index}>{content}</p> // 循环生成内容 ))} </div> )}> <Button type="primary">点击显示Popover</Button> </Popover> ); }; export default PopoverWithLoopContent; ``` 上述代码中,我们首先定义了一个要循环生成的内容数组`contentArray`。然后,在`Popover`组件的`content`属性中,我们使用了JSX中的循环语法`map`函数,来对`contentArray`进行遍历并生成对应的内容。在循环过程中,我们为每个内容项添加了一个唯一的`key`属性。 最后,我们将`PopoverWithLoopContent`组件进行导出并在其他组件中使用,当点击按钮时,就会显示包含循环生成内容的Popover组件。 注意:在实际开发中,可以根据实际需要进一步扩展和自定义循环生成的内容。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

业火之理

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值