VueJS组件使用scrollIntoView()

27

我正在尝试使用document.getElementById().scrollIntoView()在vue组件中实现跳转到div的功能。

如果我在组件内调用函数,该功能可以正常工作。但是,如果我尝试使用ref从父组件调用函数,则元素不会滚动到视图中。

父组件是一个页面,子组件是页面中的选项卡。

这是位于父组件中的子Vue组件:

<el-tab-pane label="Solution Details" name="Solution Details" v-loading="loading">
                <solution-details
                    :formData="response"
                    ref="solutionDetails"
                    @done="$emit('done')">
                </solution-details>
            </el-tab-pane>

有一个SolutionDetails.Vue子组件,它有一个ref="solutionDetails"。 我在父组件中使用子组件的ref来调用此方法

handleClick(command) {
            this.activeTab = 'Solution Details';
            this.$refs.solutionDetails.showCurrent(command);
        },

子组件中有一个 showCurrent 函数,应该基于一个名为 "command" 的参数进行执行。这是在 子组件中 定义的函数。


methods: {
        showCurrent(index) {
            document.getElementById(index).scrollIntoView();
        },

如您所见,showCurrent应该获取页面中的元素并滚动到视图中。如果SolutionDetails.vue是活动选项卡,则相应的元素会被滚动到视图中。但如果我从其他选项卡执行父函数,则会执行this.activeTab = 'Solution Details';,即活动选项卡正在更改为SolutionDetails.vue,但请求的元素未滚动到视图中。

当其他选项卡为activeTab时,您应该怎么做才能滚动到一个元素?

4个回答

25

实际上,你需要在组件中引用该元素。例如:

this.$refs.[ref name here].$el.scrollIntoView({ behavior: 'smooth' });

5
请注意,如果将ref添加到常规的HTML元素(而不是自定义的Vue元素)中,则不应使用$el。有关更多详细信息,请参见此答案:https://dev59.com/Brbna4cB1Zd3GeqPjOkp#58393099 - Liran H
1
这个 $el 真的救了我的晚上。 - Luckybug

24
问题在于调用了scrollIntoView之后,该选项卡尚未在页面上呈现,因为渲染是异步的。实质上,在调用时,页面尚未完成渲染。
this.activeTab = 'Solution Details';

Vue不会立即渲染页面,它只是将渲染排队。然而,在此之后,您告诉Vue查找已呈现的元素并滚动到该元素。但是该元素目前尚不存在。

我认为解决这个问题的第一步是使用$nextTick

this.$nextTick(() => this.$refs.solutionDetails.showCurrent(command))

在尝试滚动到视图之前,应该等待需要发生的渲染。


我完全忘记了异步的本质。我最近才开始使用它们。非常感谢! - benedemon
@tony19 感谢您的回答!对我来说,nextTick() 不起作用,但 setTimeout() 可以。在这种情况下,它们不应该是相同的吗? - Bhargav Shah

3

1:给你想要的元素一个 ref 名称。在父元素的函数内部,最好尝试使用 console.log(this.$refs.[ref_name]) 来检查哪个部分会产生影响。这并不总是父元素。它真正取决于你的CSS结构。当提交表单并获得错误消息时,视图将转到您想要的部分。

if(this.errorMessage) {
    this.$refs.[ref_name].scrollIntoView();
}

2:关于Vue.JS多步骤表单 在处理像注册这样的过程时,使用步骤是很正常的。 现在我们的问题是,视图将与第一步相同。 例如,如果第一步表单非常长并且需要滚动,那么转到第二步时,视图将停留在底部。 在这里我们可以做些什么来保持视图在顶部: 给顶部元素一个ref名称,如ref="top"。 在所有步骤提交函数中,只需添加此内容即可保持下一页在顶部:

this.$refs.top.scrollIntoView();

1
请注意,如果ref在具有v-for的元素中,将返回元素数组。 - Flimm

0
我的解决方案是将这个放在mounted钩子中:
setTimeout(() => {
      this.scrollTo();
    }, "100");

在方法中:

scrollTo() {
      this.$refs.target.scrollIntoView();
    },

1/10秒足以让组件加载完成,对我的眼睛来说是无法察觉的。它看起来瞬间完成。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接