what

受到了一次【物理】打击,引发的思考。

why

本来打算做一个 Mas OS 的 demo,本以为会是件很简单的事,结果自从基本架子搭起来以后,一方面要找素材,另一方面要从零开始造轮子。两件事都非常折磨人,没有太多找素材的经验,造一个好的轮子,也要花不少的时间。今天打算造一个 Mac OS 的菜单,实现 Mac 上的菜单功能,发现事情远没那么简单,没有很好的一个思路。

随即想去看看 ant-design 的 Trigger 的实现方式,结果就受到了打击。

how

我原有的一个思路是,实现一个 Trigger ,对于 React 来说,最主要的就是使用 React.createPortal 这个方法了,因为 Trigger 基本上都是根据子类元素的位置去确定弹出的内容的位置,所以必然是要插入一个 position 为 absolute 的元素,然后根据子元素的位置,去计算弹出的位置。

// 以下皆伪代码,几个原思路的核心功能,源代码被我一怒之下删了,冲动是魔鬼啊。

// 要实现的组件类似这样

<Trigger
  type="click"
  positon="bottom"
  popContent={<div>this is pop</div>}
>
  <button>Open</button>
</Trigger>

// 1. 插入弹窗,dom 是真实的 document 元素,popContent 是传入需要渲染的 react 节点,即 <div>this is pop</div> 
render() {
  return <div>
    {props.children}
    {React.createPortal(popContent, dom);}
    </div>
}

// 2. 创建 dom
const dom = document.createElement('div');
dom.style.position = "display";

// 3. 计算 popContent 的位置
// 利用 ref 得到 children 元素的位置,然后根据 offset 得到左和上的距离,再加上元素的宽高即可计算出 popContent 的 top 和 left 是多少

// 4. 点击屏幕非 popContent 的空白处,关闭 popContent
// 监听点击事件,通过判断点击位置是否在 popContent 内,而决定是否需要关闭

理想状态就是这样的,看起来一切都可行,

然而。。。

还是我太天真了。

到了第四步,在 useEfect 中添加一个全局的监听事件,肯定需要清除这个事件,然而清除之后又导致下一次触发 useEfect 的时候,又无法重新监听新的 ref 。后来实在没有好的想法了,就想着去看看别人的实现方式,首先就想到了 popover,经过一系列的排查,最终发现底层使用的是 rc-trigger, 于是就看 rc-trigger 的实现方式,看了一会,发现自己耐不住心去看,一大串一大串的代码,绕来绕去,看的头疼。

总结

于是这就造就了我今天迷茫的一天,还想着有一天弄个 ant-design 源码解析系列呢,但如果这点代码都看不下去,以后怎么办?

(完)


作者: Kavience 本文链接: http://www.kavience.com/think/a-lost-day.html 转载请注明:《迷茫的一天》转自 http://www.kavience.com/think/a-lost-day.html,原作者:Kavience 版权声明: 自由转载-非商用-非衍生-保持署名(创意共享3.0许可证)