Vue.nextTick:在下次 DOM 更新循环结束之后执行延迟回调,实现聊天框自动下拉到底部。

最早学习vue的时候,在vue官方文档看到过这个api,但是不知道具体有什么用,昨天在实习项目中遇到一些问题,Vue.nextTick可以很好的解决。
想要实现到功能是一个聊天框,当发送信息时,可以自动下拉到聊天框底部。
想要实现这个功能很简单,只需要获取到聊天框到DOM对象,然后是它到scrollTop属性等于scrollHeight属性就可以了。
Vue.nextTick:在下次 DOM 更新循环结束之后执行延迟回调,实现聊天框自动下拉到底部。_第1张图片

	var oDiv = document.getElementsByClassName('chatBox')[0]
	if (oDiv !== undefined) {
		oDiv.scrollTop = oDiv.scrollHeight
	}

但是在vue项目中就有一些麻烦的地方,你需要在视图更新的时候去执行上面这些代码,我实现聊天框的代码如下

			<div class="chatBox">
              <div
                class="dialogue clean"
                v-for="(item, index) in dialogueData"
                :key="index"
              >
                <div class="clientBox" v-if="item.type == '0'">
                  <i class="headImg"></i>
                  <div class="chatContent">
                    <i class="cover"></i>
                    <i class="triangle"></i>
                    {{ item.Question }}
                  </div>
                </div>
                <div class="myBox" v-if="item.type == '1'">
                  <div class="chatContent">
                    <i class="cover"></i>
                    <i class="triangle"></i>
                    {{ item.Question }}
                  </div>
                  <i class="headImg"></i>
                </div>
              </div>
            </div>

数组都存入到dialogueData数组里,然后v-for进行循环。用户每发送一条信息,就会在dialogueData里添加一个数据,之后发送请求,返回回复内容并进行渲染

      httpPost('/eweb/eweb-common.IntelligentCustInfoQry.do', params)
        .then(res => {
          if (res.ReturnCode === '000000') {
            this.sendMsgData.Question1 = res.Answer
            const temp1 = {
              type: '0',
              Question: this.sendMsgData.Question1
            }
            this.dialogueData.push(temp1)
            // 回到底部
            var oDiv = document.getElementsByClassName('chatBox')[0]
            if (oDiv !== undefined) {
              oDiv.scrollTop = oDiv.scrollHeight
            }
          }
        })
        .catch(err => {
          window.console.log('err--', err)
        })

Vue.nextTick:在下次 DOM 更新循环结束之后执行延迟回调,实现聊天框自动下拉到底部。_第2张图片
自己发的内容是可以进行拉到底部到,但是请求回来到数据就不行,在添加数组之后进行拉底,但是此时DOM元素还没有进行渲染,当时没有发现是这个问题,就在watch里对dialogueData数组进行监听后进行操作,但还是不行,之后想在scrollTop上直接加上一个聊天框的高度,但是有两个问题,第一不知道给我返回的有几行文字,高度不固定;第二就是,你会发现你根本加不上,原因好像是因为元素的scrollTop最大也只能是和scrollHeight的值相等(我猜的,但应该就是吧)。之后没办法,就百度,百度出来解决方法是写在updated周期钩子里,果然解决了,可以同步刷新了(百度NB),同时我也反映过来来,是渲染但问题,大家都知道,代码尽量不要写在updated里,一更新视图就触发,我的页面里刚好有一个倒计时,每过一秒就会执行一遍,本着优化的目的,还是不用里,这时候就想起了Vue.nextTick,Vue官方文档的用法:在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM。
所以,可以把代码改成这样

      httpPost('/eweb/eweb-common.IntelligentCustInfoQry.do', params)
        .then(res => {
          if (res.ReturnCode === '000000') {
            this.sendMsgData.Question1 = res.Answer
            const temp1 = {
              type: '0',
              Question: this.sendMsgData.Question1
            }
            this.dialogueData.push(temp1)
            this.$nextTick(() => {
              var oDiv = document.getElementsByClassName('chatBox')[0]
              if (oDiv !== undefined) {
                oDiv.scrollTop = oDiv.scrollHeight
              }
            })
          }
        })
        .catch(err => {
          window.console.log('err--', err)
        })

在请求成功的回调里使用,可以在DOM更新后执行里面的方法,并且只会执行一次,问题解决~

你可能感兴趣的:(Vue.nextTick:在下次 DOM 更新循环结束之后执行延迟回调,实现聊天框自动下拉到底部。)