从0开始制作IM界面踩坑记 - litong534/web GitHub Wiki

我是在react基础上进行开发的,所以示例代码均采用项目源码,其他框架可自行调整

整体布局

如果是圣杯结构,在safari以及微信浏览器等的环境中,整个窗体是有拖动回弹特效的,此处要注意顶部底部区域使用position: fixed,中部切不可使用除static之外的布局,否则会导致拖动回弹时的页面出现预料之外的效果。 可以使用padding以及height,来控制聊天内容的可视区域,使该可视区域出现滚动条。

输入框

当输入框触发聚焦事件,出现虚拟键盘时,在ios或者其他机型有可能出现虚拟键盘遮挡住输入框的情况,我在研究过程中发现,输入框弹起时,整个body其实是视口被挤压了,所以会出现滚动条,这时候可以手动控制body的滚动高度

    if (inputRef && inputRef.current) {
      setTimeout(() => {
        document.body.scrollTop = document.body.scrollHeight;
      }, 300);
    }

当输入框触发失焦事件,虚拟键盘收回时,ios一部分机型的body并没有回到原位,并且导致页面中一些事件失效(如button的onclick等),这时可以手动将页面归位

    setTimeout(() => {
      window.scrollTo(0, 0);
      document.body.scrollTop = 0;
    }, 300);

由于是im聊天,页面初始化以及发送新消息时,均需要将聊天内容可视区域滚动到底部,使用一行表达式即可达到效果

  imRef.current.scrollTop = imRef.current.scrollHeight;

当需要加载历史消息时,由于是在消息数组头部插入数据,这时聊天内容可视区域会变动,影响用户体验,这时我们可以在函数外部记录一个当前的scrollHeight值,在数据加载完毕,页面渲染结束时立即滚动到之前记录的位置,就可以解决了

  const handleLoadingHistoryClick = () => {
    lastIMScrollHeight = imRef.current.scrollHeight;
  };
// 当历史数据加载完毕时
 imRef.current.scrollTop = imRef.current.scrollHeight - lastIMScrollHeight;