文章目录
1. 重点提炼
- 滚动行为
- 后退/前进
2. 滚动行为
前端路由并没有重载整个浏览器,只是通过 DOM
进行了局部更新。所以,有的时候,浏览器的一只状态会被保持,比如 滚动条,当我们在一个页面中滚动滚动条,然后跳转到另外一个页面,滚动条会保持在上一个页面中,我们其实更希望滚动条能回到页面顶部,就像重载了整个页面一样
const router = new VueRouter({
routes: [...],
scrollBehavior: () => ({
y: 0 })
});
3. 后退/前进
正对 后退/前进 行为,会提供一个 savedPosition
参数,通过该参数返回历史记录中的滚动值
scrollBehavior (to, from, savedPosition) {
// console.log(savedPosition)
if (savedPosition) {
return savedPosition
} else {
return {
x: 0, y: 0 }
}
}
scrollBehavior
方法接收 to
和 from
路由对象。第三个参数 savedPosition
当且仅当 popstate
导航 (通过浏览器的 前进/后退 按钮触发) 时才可用。
这个方法返回滚动位置的对象信息,长这样:
{ x: number, y: number }
{ selector: string, offset? : { x: number, y: number }}
(offset 只在 2.6.0+ 支持)
如果返回一个 falsy (译者注:falsy 不是 false
,参考这里)的值,或者是一个空对象,那么不会发生滚动。
如果要模拟“滚动到锚点”的行为:
scrollBehavior (to, from, savedPosition) {
if (to.hash) {
return {
selector: to.hash
}
}
}
我们还可以利用路由元信息(下一篇的内容)更细颗粒度地控制滚动。
4. 实例
4.1 example01
\app\src\App.vue
<template>
<div id="app">
<h1>我的主页</h1>
<div id="nav">
<router-link exact to="/">Home</router-link>
<span> | </span>
<router-link to="/about">About</router-link>
<span> | </span>
<router-link to="/view">Detail</router-link>
</div>
<hr />
<router-view></router-view>
</div>
</template>
<script>
export default {
name: 'App'
}
</script>
<style>
.router-link-active {
color: red;
}
</style>
\app\src\views\Home.vue
<template>
<div>
<ul>
<li v-for="i of 100">{
{i}}</li>
</ul>
</div>
</template>
<script>
export default {
name: "Home"
}
</script>
<style>
</style>
\app\src\views\Detail.vue
<template>
<div>
<ul>
<li v-for="i of 100">{
{i}}</li>
</ul>
</div>
</template>
<script>
export default {
name: "Detail"
}
</script>
<style>
</style>
\app\src\views\About.vue
<template>
<div>
<ul>
<li v-for="i of 100">{
{i}}</li>
</ul>
</div>
</template>
<script>
export default {
name: "About"
}
</script>
<style>
</style>
\app\src\router\index.js
import Vue from 'vue';
import VueRouter from 'vue-router';
import Home from '@/views/Home';
import About from '@/views/About';
import Detail from '@/views/Detail';
Vue.use(VueRouter);
let router = new VueRouter({
mode: 'history',
routes: [
{
path: '/',
name: 'home',
component: Home
},
{
path: '/about',
name: 'about',
component: About
},
{
path: '/view',
name: 'view',
component: Detail
}
]
});
export default router;
现在有三个页面,内容很多,都会有滚动条。
参考:https://https://github.com/6xiaoDi/blog-vue-Novice/tree/a2.27
Branch: branch07commit description:a2.27(example01-1——滚动案例基本框子实现)
tag:a2.27
4.2 example02
跳转页面在Chrome
下做了优化,很多问题都解决了,我们看看火狐
比较严重。
其实浏览器在页面跳转(刷新)的过程中,会记录一个东西 =>
当前页面的滚动条的位置
当我们刷新页面后,滚动条还在原来的位置,不会跑到最开始的位置。
导航设置固定定位及样式,方便后面点击操作。
\app\src\App.vue
<template>
<div id="app">
<h1>我的主页</h1>
<div id="nav">
<router-link exact to="/">Home</router-link>
<span> | </span>
<router-link to="/about">About</router-link>
<span> | </span>
<router-link to="/view">Detail</router-link>
</div>
<hr />
<router-view></router-view>
</div>
</template>
<script>
export default {
name: 'App'
}
</script>
<style>
.router-link-active {
color: red;
}
#nav {
padding: 10px 0;
position: fixed;
width: 100%;
left: 0;
top: 0;
background: rgba(0,255,0,.3);
}
</style>
问题 => 我们往下滚动,然后切换about
页面,此时滚动条还是保留到之前的位置。
参考:https://https://github.com/6xiaoDi/blog-vue-Novice/tree/a2.28
Branch: branch07commit description:a2.28(example01-2——滚动行为问题)
tag:a2.28
4.3 example03
这种效果我们肯定不需要的 => 每次跳转导航,肯定是希望滚动条是在最顶层
的。
这其实就是我们本节说的滚动行为。
在路由配置中,专门有一个处理滚动行为的函数。
return
出去一个对象就行了。包含两个值 => x
横向滚动条 y
纵向滚动条
\app\src\router\index.js
scrollBehavior() {
return {
x: 0,
y: 0
}
}
我们点击链接,肯定是想看新页面,即跳转到滚动条滚动到最顶层。
但是还是有问题的,我们点击浏览器的回退
按钮,滚动条也跑到最顶部了。 => 这个肯定是不符合要求的
参考:https://https://github.com/6xiaoDi/blog-vue-Novice/tree/a2.29
Branch: branch07commit description:a2.29(example01-3——滚动行为前进/回退问题)
tag:a2.29
4.4 example04
回退 => 回到上一次的浏览状态 (但是不是所有的回退都是这样的要求,具体看用户需求和体验了)
因此针对这种行为,我们还需做特殊处理。
scrollBehavior
=> 接收三个参数 => to
, from,
savedPosition
前两个比较简单,就是从哪来到哪去
第三个参数比较特殊,打印看看
scrollBehavior(to, from, savedPosition) {
console.log(savedPosition);
return {
x: 0,
y: 0
}
},
导航跳转都是null
值,但是点击后退 =>
这个时候打印了一个对象
,里有x
和y
,它代表上一次滚动条位置信息,如果点击链接产生的跳转(主动跳转),它是空
,只有点击前进和后退的时候,它才有值。
通过这个就可以知道,我们到底点击的是链接还是前进后退了。
=> 即代表调用的浏览器的历史记录。
参考:https://https://github.com/6xiaoDi/blog-vue-Novice/tree/a2.30
Branch: branch07commit description:a2.30(example01-4——scrollBehavior方法的savedPosition参数)
tag:a2.30
4.5 example05
scrollBehavior(to, from, savedPosition) {
console.log(savedPosition);
if (savedPosition) {
// 调用的浏览器的历史记录
return savedPosition;
}
return {
x: 0,
y: 0
}
},
这就满足要求了。 => 移动端一些浏览器也会有问题,最好加上这个逻辑。
参考:https://https://github.com/6xiaoDi/blog-vue-Novice/tree/a2.31
Branch: branch07commit description:a2.31(example01-5——优化滚动行为)
tag:a2.31
当然到底是哪些路由希望回到原位置的,就需要看页面设计和产业的需求来决定了。
5. 异常滚动
2.8.0 新增
你也可以返回一个 Promise 来得出预期的位置描述:
scrollBehavior (to, from, savedPosition) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve({
x: 0, y: 0 })
}, 500)
})
}
将其挂载到从页面级别的过渡组件的事件上,令其滚动行为和页面过渡一起良好运行是可能的。但是考虑到用例的多样性和复杂性,官方仅提供这个原始的接口,以支持不同用户场景的具体实现。
考虑到在blog中不好体现代码更改的位置,小迪才用github托管代码,大家可以查看github,看到详细版本修改过程,搭配博客学习。
(后续待补充)