滚动行为

在应用中,有时会遇到这样的场景,当页面内容比较多时,整个页面就会变得可滚动,这时当我们进行路由切换时,或者从其他路由切换到这个页面时,想让页面滚动到顶部,或者保持原先的滚动位置,就像重新加载页面那样,需要记录滚动的距离,而 Vue Router 可以支持这种操作,它允许我们自定义路由切换时页面如何滚动。

当创建一个 Router 实例时,设置 scrollBehavior 方法,如示例代码7-12-1所示。

var router = VueRouter.createRouter({
    routes: [...],
    scrollBehavior(to, from, savedPosition) {
        // return 期望滚动到哪个位置
    }
})

当页面路由切换时会进入这个方法,scrollBehavior 方法接收 tofrom 路由对象,它们分别表示切换前和切换后的路由,第三个参数 savedPosition 是一个对象,结构是 {left: number, top: number},表示在页面切换时所存储的页面滚动的位置,如果页面不可滚动,就是默认值 {left: 0, top: 0}。可以采用以下配置来设置跳转到原先滚动的位置,代码如下:

scrollBehavior(to, from, savedPosition) {
    if (savedPosition) {
        return savedPosition
    } else {
        return { left: 0, top: 0 } // 默认不滚动
    }
}

savedPosition 方法的返回值决定了页面要滚动到哪个位置(会触发页面滚动,有时我们可能会看到这个过程)。如果要模拟 “滚动到锚点” 的行为,可以试试下面这段代码:

<router-link to="/user#nickname">姓名</router-link>
...
scrollBehavior(to, from, savedPosition) {
    if (to.hash) {
        return {
            selector: to.hash  // #nickname
        }
    }
}

有时候,我们需要在页面滚动之前稍作等待。例如,当处理过渡时,我们希望等待过渡结束后再滚动。要做到这一点,可以返回一个 Promise,代码如下:

scrollBehavior(to, from, savedPosition) {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve({ left: 0, top: 0 })
        }, 500)
    })
}