跳到主内容

vue中调用scrollIntoView()无效

· 2分钟阅读

问题

有一个场景,父组件监听子组件加载完成后,通过 $emit 通知父组件,然后父调用 this.$refs.detail.scrollIntoView() ,但是很遗憾,页面没有实现滚动效果。附上代码。

组件代码

<button @click="goToDetail">切换</button>
<el-tab-pane label="文章详情" name="ArticleDetail" v-loading="loading">
<article-detail :formData="data" ref="articleDetail" @done="$emit('done')"> </article-detail>
</el-tab-pane>

父组件通过 ref 调用 ArticleDetailscrollIntoView() 方法。

{
methods: {
goToDetail() {
this.activeTab = 'ArticleDetail'
this.$refs.articleDetail.showCurrent(index);
}
}
}

ArticleDetail 组件的 showCurrent() 方法定义如下:

methods: {
showCurrent(index) {
const el = document.getElementById('detail-' + index);
if (el) {
el.scrollIntoView();
}
}
}

原因

由于 this.activeTab = ArticleDetail 切换 tab 后,因为是异步渲染的,这时候页面还没完全渲染完成就调用 this.$refs.articleDetail.showCurrent(index),获取的 document.getElementById('detail-' + index) 为 null,导致 scrollIntoView() 方法无效。

解决

解决方法很简单,vue 提供了 this.$nextTick() 方法,可以在页面渲染完成后,获取到渲染后到DOM元素,所以只需要在 this.$nextTick() 的回调函数中调用 this.$refs.articleDetail.showCurrent(index); 即可。

{
methods: {
goToDetail() {
this.activeTab = 'ArticleDetail'
this.$nextTick(() => {
this.$refs.articleDetail.showCurrent(index);
});
}
}
}