2020.11.6 自己实现小红点提示(后来才发现组件库里有233
今天要做一个功能:当面试官推送给考生一道题时,考生侧边栏中的“题目”标签页上要有相关提醒。
我是第一次实现这个功能,首先我需要知道“小红点”是怎么做出来的。
小红点可以用CSS画出来:
<div class="point"></div>
然后想,红点应该放在哪里。我是这样想的,虽然红点是在“题目“右上角,但是不应该放在”题目“标签页中。如果是放在里面,那不点开这个,是看不到红点的。
所以我先考虑把红点放在了Tabs
中,与两个TabPanel
并排,效果有了,推送题目的时候红点也会出现,查看后也会消失。但是,我这里的布局发生了变化:
可以看到,有红点时,聊天和题目都往右挪了一些位置,我不希望它们发生变化。所以再次思考小红点的位置。
然后我突然想到,这个红点,肯定不能放在”题目“的TabPanel
中,那能不能放在”聊天“的TabPanel
中呢?因为红点的隐藏与显示的逻辑,是在整个函数组件中判断的,所以其实放在哪个标签中,都不会影响它的逻辑。而且反正看了题目小红点就会消去,所以放在”聊天“中应该是可以的。
最后我就是这么做的,需要说一下的是小红点是怎么放在题目上面的。我使用的是绝对定位,top:45px; right:260px
,这样在全屏的情况下,小红点就落在了题目右上角。但是这样其实是不对的,position:absolute
是相对上一个被position
定位的元素,因此此时小红点是相对整个窗口定位,随着窗口变化,小红点也乱动。所以我把侧边栏设置为position:relative
,这样就稳定了。加深了我对position
的理解。
然后是小红点根据推送题目与否,显示与隐藏的逻辑。这个我花了很长时间,先是思考通过什么来判断收到了题目推送,然后是根据推送,怎么设计逻辑。
我找到了考生处显示题目的组件,理解了组件的功能后,其中的n=problems.length
,就是统计题目的长度,每推送过来一个题目,都会存在problems
中,然后通过取problems[n-1]
,来获得最新一道题的信息并展示。所以我就想通过判断n是否比上一个n大,来决定是否推送了新题目。
(还需要说,我也找到了发送题目的代码,但是我认为,发送题目与接收题目还有一个网络传输过程,通过接收题目与否来判断,更加合理)
当有新题目推送过来的时候,不是所有情况都需要显示红点的,当我们在”聊天“标签页时,还没有看到题目,需要显示小红点;当我们在”题目“标签页时,页面可以响应式地展示新推送过来的题目,就不需要展示小红点了。
题目->聊天:不需要展示红点,而且在下一道题推送过来之前,都不展示红点。
聊天->题目:展示红点,切换到”题目“标签页时,红点消失,而且在下一道题推送过来之前,都不展示红点。
已读的题目,刷新或者断线重连后都还是已读状态;同理,未读的题目,也一直是未读状态。
基本的逻辑已经梳理完了,还有一些实现细节。
首先是一个useState
的model
集合,如果推送了新的题目,就通过setHasNew
将hasNew
设置为true
(初始状态设置为false)。
通过Tabs
的OnChange
回调方法,该方法会将当前TabPanel
的key
作为返回参数。我们可以利用它来帮助我们判断当前是从”聊天“切到”题目“,还是从”题目“切到”聊天“。为了实现这个判断,我们需要再设置一个const [keyNum, setKeyNum] = useState("0")
,我们用它表示切换前的TabPanel
.
然后是展示的逻辑,如果有新题目,且我们不在”题目“标签页,那就展示,否则隐藏。
刷新的情况还没完成,因为一刷新,n就重新赋值了,会经历从初始值开始的赋值,而这时会错误地将题目设置为未读。等周三看看吴老师怎么弄。
可以使用sessionStorage
来存储。