问题
有一个场景,父组件监听子组件加载完成后,通过 $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
调用 ArticleDetail
的 scrollIntoView()
方法。
{
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);
});
}
}
}