小编典典

当外部div的大小发生变化时,可滚动的div会停留在底部

reactjs

这是一个聊天应用示例->

这里的想法是.messages-container尽可能多地占用屏幕。在中.messages- container.scroll保存消息列表,如果还有更多消息,则滚动屏幕尺寸。

现在,考虑这种情况:

  1. 用户滚动到对话的底部
  2. .text-input,动态地变大

现在,文本输入增加了,而不再是用户滚动到对话的底部,而是不再看到底部。

解决该问题的一种方法,如果我们使用react,请计算文本输入的高度,如果有任何变化,请让.messages-container知道

componentDidUpdate() {
  window.setTimeout(_ => {
    const newHeight = this.calcHeight();
    if (newHeight !== this._oldHeight) {
      this.props.onResize();
    }
    this._oldHeight = newHeight;
  });
}

但是,这会导致明显的性能问题,这是可悲的围绕传递消息是这样的。

有没有更好的办法?我可以这样使用css来表示,当.text-input- shift upincreas 增加时,我基本上想要所有.messages-container


阅读 344

收藏
2020-07-22

共1个答案

小编典典

2:此答案的修订版

在这里flex-direction: column- reverse;,您的朋友在对齐消息容器底部的消息时会执行所有操作,就像Skype和许多其他聊天应用程序一样。

.chat-window{
  display:flex;
  flex-direction:column;
  height:100%;
}
.chat-messages{
  flex: 1;
  height:100%;
  overflow: auto;
  display: flex;
  flex-direction: column-reverse;
}

.chat-input { border-top: 1px solid #999; padding: 20px 5px }
.chat-input-text { width: 60%; min-height: 40px; max-width: 60%; }

缺点flex-direction: column-reverse;是IE / Edge /
Firefox中的错误,滚动条未显示

好处 是,您在移动设备/平板电脑上拥有〜90%的浏览器支持,而在台式机上拥有〜65%的浏览器支持,并且随着该漏洞的修复,……还有一种解决方法。

// scroll to bottom
function updateScroll(el){
  el.scrollTop = el.scrollHeight;
}
// only shift-up if at bottom
function scrollAtBottom(el){
  return (el.scrollTop + 5 >= (el.scrollHeight - el.offsetHeight));
}

在下面的代码片段中,我从上面添加了2个功能,以使IE / Edge/Firefox具有相同的行为flex-direction: column- reverse;

function addContent () {

  var msgdiv = document.getElementById('messages');

  var msgtxt = document.getElementById('inputs');

  var atbottom = scrollAtBottom(msgdiv);



  if (msgtxt.value.length > 0) {

    msgdiv.innerHTML += msgtxt.value + '<br/>';

    msgtxt.value = "";

  } else {

    msgdiv.innerHTML += 'Long long content ' + (tempCounter++) + '!<br/>';

  }



  /* if at bottom and is IE/Edge/Firefox */

  if (atbottom && (!isWebkit || isEdge)) {

    updateScroll(msgdiv);

  }

}



function resizeInput () {

  var msgdiv = document.getElementById('messages');

  var msgtxt = document.getElementById('inputs');

  var atbottom = scrollAtBottom(msgdiv);



  if (msgtxt.style.height == '120px') {

    msgtxt.style.height = 'auto';

  } else {

    msgtxt.style.height = '120px';

  }



  /* if at bottom and is IE/Edge/Firefox */

  if (atbottom && (!isWebkit || isEdge)) {

    updateScroll(msgdiv);

  }

}





/* fix for IE/Edge/Firefox */

var isWebkit = ('WebkitAppearance' in document.documentElement.style);

var isEdge = ('-ms-accelerator' in document.documentElement.style);

var tempCounter = 6;



function updateScroll(el){

  el.scrollTop = el.scrollHeight;

}

function scrollAtBottom(el){

  return (el.scrollTop + 5 >= (el.scrollHeight - el.offsetHeight));

}


html, body { height:100%; margin:0; padding:0; }



.chat-window{

  display:flex;

  flex-direction:column;

  height:100%;

}

.chat-messages{

  flex: 1;

  height:100%;

  overflow: auto;

  display: flex;

  flex-direction: column-reverse;

}



.chat-input { border-top: 1px solid #999; padding: 20px 5px }

.chat-input-text { width: 60%; min-height: 40px; max-width: 60%; }





/* temp. buttons for demo */

button { width: 12%; height: 44px; margin-left: 5%; vertical-align: top; }



/* begin - fix for hidden scrollbar in IE/Edge/Firefox */

.chat-messages-text{ overflow: auto; }

@media screen and (-webkit-min-device-pixel-ratio:0) {

  .chat-messages-text{ overflow: visible; }

  /*  reset Edge as it identifies itself as webkit  */

  @supports (-ms-accelerator:true) { .chat-messages-text{ overflow: auto; } }

}

/* hide resize FF */

@-moz-document url-prefix() { .chat-input-text { resize: none } }

/* end - fix for hidden scrollbar in IE/Edge/Firefox */


<div class="chat-window">

  <div class="chat-messages">

    <div class="chat-messages-text" id="messages">

      Long long content 1!<br/>

      Long long content 2!<br/>

      Long long content 3!<br/>

      Long long content 4!<br/>

      Long long content 5!<br/>

    </div>

  </div>

  <div class="chat-input">

    <textarea class="chat-input-text" placeholder="Type your message here..." id="inputs"></textarea>

    <button onclick="addContent();">Add msg</button>

    <button onclick="resizeInput();">Resize input</button>

  </div>

</div>

旁注1:该检测方法尚未完全测试,但应在较新的浏览器上运行。

旁注2:为聊天输入附加一个调整大小事件处理程序可能比调用updateScroll函数更有效。

注意:感谢 HaZardouS 重用其html结构

2020-07-22