Vue 0基础学习路线(25)—— 图解深度详述vue路由的滚动行为火狐浏览器等出现的问题和涉及后退/前进功能的问题和异常滚动及详细案例(附详细案例代码解析过程及版本迭代过程)

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 方法接收 tofrom 路由对象。第三个参数 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

扫描二维码关注公众号,回复: 12043761 查看本文章
<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: branch07

commit 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: branch07

commit 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: branch07

commit 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值,但是点击后退 =>

这个时候打印了一个对象,里有xy,它代表上一次滚动条位置信息,如果点击链接产生的跳转(主动跳转),它是,只有点击前进和后退的时候,它才有值。

通过这个就可以知道,我们到底点击的是链接还是前进后退了。

=> 即代表调用的浏览器的历史记录。

在这里插入图片描述

参考:https://https://github.com/6xiaoDi/blog-vue-Novice/tree/a2.30
Branch: branch07

commit 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: branch07

commit 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,看到详细版本修改过程,搭配博客学习。



(后续待补充)

猜你喜欢

转载自blog.csdn.net/u013946061/article/details/107812248