最早学习vue的时候,在vue官方文档看到过这个api,但是不知道具体有什么用,昨天在实习项目中遇到一些问题,Vue.nextTick可以很好的解决。
想要实现到功能是一个聊天框,当发送信息时,可以自动下拉到聊天框底部。
想要实现这个功能很简单,只需要获取到聊天框到DOM对象,然后是它到scrollTop属性等于scrollHeight属性就可以了。
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)
})
自己发的内容是可以进行拉到底部到,但是请求回来到数据就不行,在添加数组之后进行拉底,但是此时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更新后执行里面的方法,并且只会执行一次,问题解决~