让DIV的滚动条(内容)自动滚动到最底部,包含使用vue框架的区别。

在我的移动端页面需要做一个固定高度的DIV,每次往这个DIV中增加内容的时候我需要将滚动条自动滚动至最底部保证每次看到的都是最新的内容。(这样增加了用户的体验度好感,就像微信的聊天窗口一样。)我利用了JavaScript中的scrollTop = scrollHeight这两个属性来实现,代码如下:

html代码:

<div class="box" style="width:500px;height:100px; border:1px solid black;overflow-x: hidden;overflow-y: auto;margin:50px auto 0;padding: 3px;"></div>
<button onclick="add()" style="display:block;width:100px;height:20px;margin:20px auto;">添加</button>

JavaScript代码:

<script>
       function add(){
           var div = document.getElementsByClassName('box')[0];
           var time = new Date().getTime();
           div.innerHTML += `<div>当前时间:${time}</div>`;
           div.scrollTop = div.scrollHeight;
       }
</script>

按照以上思路每次都能如愿的让滚动条滑动至最底部:

可是我使用vue框架的时候就不好使了,每次滚动条没有滑动到最底部,而是底部还有一条信息被隐藏了,很是恼火!

html代码:

<div class="app">
     <div ref="box" class="box" style="width:500px;height:100px; border:1px solid black;overflow-x: hidden;overflow-y: auto;margin:50px auto 0;padding: 3px;">
          <div v-for="item in items">当前时间:{{item.time}}</div>
      </div>
      <button @click="add" style="display:block;width:100px;height:20px;margin:20px auto;">添加</button>
</div>

JavaScript代码:

<script>
    new Vue({
           el:'.app',
           data:{
            items:[]
           },
           methods:{
               add(){
                    var div = this.$refs.box,
                        time = new Date().getTime(),
                        item = {'time':time};
                        
                    this.items.push(item);
                    div.scrollTop = div.scrollHeight;
               }
           }
       })
 </script>

效果图:

问题分析:由于vue采用虚拟dom,我每次生成新的消息时获取到的div的scrollHeight的值是生成新消息之前的值,所以造成每次都是最新的那条消息被隐藏掉了!为了论证我的分析是正确的特意做个试验,把每次vue在重新渲染dom的前后时间点和DIV的scrollHeight打印出来以做对比:

new Vue({
           el:'.app',
           data:{
            items:[]
           },
           beforeUpdate(){
            var div = this.$refs.box;
               console.log(`我被更新Dom之前,更新时间:${new Date().getTime()},更新前的div.scrollHeight是:${div.scrollHeight}`)
           },
           updated(){
            var div = this.$refs.box;
               console.log(`我被更新了Dom,更新时间:${new Date().getTime()},前后时间差:${new Date().getTime() - time} 毫秒,更新后的div.scrollHeight是:${div.scrollHeight}`)
           },
           methods:{
               add(){
                    time = new Date().getTime();
                    var div = this.$refs.box;
                    var item = {'time':time};
                    this.items.push(item);
                    console.log(`点击了添加按钮,更新时间:${time},此时的div.scrollHeight是:${div.scrollHeight}`)
                    div.scrollTop = div.scrollHeight;
               }
           }
       })

查看打印日志:

果然与我分析的一致!既然找到了原因那么就好解决问题了,我们在vue的updated状态之后去尝试获取DIV的scrollHeight就能保证是最新的内容高度了。使用异步处理setTimeout函数获取最新的div.scrollHeight,这样就能确保滚动条每次滑动至最底部!代码如下:

new Vue({
           el:'.app',
           data:{
            items:[]
           },
           beforeUpdate(){
            var div = this.$refs.box;
               console.log(`我被更新Dom之前,更新时间:${new Date().getTime()},更新前的div.scrollHeight是:${div.scrollHeight}`)
           },
           updated(){
            var div = this.$refs.box;
               console.log(`我被更新了Dom,更新时间:${new Date().getTime()},前后时间差:${new Date().getTime() - time} 毫秒,更新后的div.scrollHeight是:${div.scrollHeight}`)
           },
           methods:{
               add(){
                    time = new Date().getTime();
                    var div = this.$refs.box;
                    var item = {'time':time};
                    this.items.push(item);
                    //此时必须异步执行滚动条滑动至底部
                    setTimeout(()=>{
                        console.log(`点击了添加按钮,更新时间:${time},此时的div.scrollHeight是:${div.scrollHeight}`)
                        div.scrollTop = div.scrollHeight;
                    },0)
               }
           }
       })

现在来打开控制台看看:

好了,到这问题完美解决了!

猜你喜欢

转载自blog.csdn.net/weixin_41190571/article/details/86509383
今日推荐