vue-router实现原理

15 篇文章 0 订阅

目录

hash模式

window.location

代码实现

history模式

window.history

代码实现

路由守卫事件

路由生命周期执行的先后顺序

路由与组件声明周期的先后顺序

router-link 与 a

$route.matched

问题

不同路由跳转到相同页面,缓存问题


vue-Router实现了在不刷新页面的情况下,通过改变路由的URL去改变页面的视图

hash模式

修改hash值,渲染hash值下对应的组件;

也可通过浏览器前进、后退操作,对hashchange事件进行监听,当hash值发生变化时,渲染该hash值下对应的组件

hash值改变的同时,浏览器会自动修改路由栈

window.location

代码实现

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <a href="#/home">Home</a>
    <a href="#/a">页面A</a>
    <div id="page"></div>

    <script>
      window.addEventListener("hashchange", function (event) {
        let hashId = window.location.hash;
        if (hashId == "#/home") {
          document.getElementById("page").innerHTML = "首页";
        } else if (hashId == "#/a") {
          document.getElementById("page").innerHTML = "A页面";
        }
      });
    </script>
  </body>
</html>

点击Home,效果如下

点击home,再点击页面A, history栈长度变化。说明浏览器会自动修改历史访问栈

 

history模式

history模式就是利用pushState()、replaceState()改变历史记录, 同时渲染响应路由组件;

也可通过浏览器前进、后退操作,监听popstate事件实现浏览器路由跳转时, 同时渲染响应路由组件;

window.history

length

历史记录个数,history.back()操作不会减少记录个数

state

可认为是该页面的接收参数,根据pushState()方法可向具体URL传参state

pushState(state, title, url)

  • 修改浏览器历史记录,入栈,但是不操作浏览器的前进、后退;
  • 如果为绝对路径,需要与当前路径同源

replaceState(state, title, url)

替换当前历史记录

back():操作浏览器后退

forward():操作浏览器前进

go():操作浏览器跳往第几个栈记录

代码实现

<template>
  <div>
    <div>home页</div>
    <div @click="pushUrl('/home')">点我</div>
  </div>
</template>

<script>
export default {
  name: "",
  data() {
    return {

    };
  },
  mounted() {
    // 监听浏览器前进、回退事件
    window.addEventListener("popstate", (event) => {
      console.log("--------popstate---------");
      console.log(event.state)
      if (event.state.state == "/home") {
          //渲染对应的组件
        } else if (event.state == "/a") {
          //渲染对应的组件
        }
    });
  },
  methods: {
    add() {
      this.a++;
    },
    pushUrl(url) {
      window.history.pushState({page: url}, "page 2", url); //此时算上首页,栈中共有两条记录
       if (event.state.state == "/home") {
          //渲染对应的组件
        } else if (event.state == "/a") {
          //渲染对应的组件
        }
    },
  },
};
</script>

<style lang="less" scoped></style>

路由守卫事件

路由生命周期执行的先后顺序

刷新进入页面A 

 从'/a'进入’/b'

  从'/a'进入’/a?name=aa'

路由与组件声明周期的先后顺序

进入A页面:执行顺序,路由的声明周期 > 组件的生命周期

 离开A页面(从 '/a' 到 '/' ):执行顺序,路由的声明周期 > 组件的生命周期

router-link 与 a

  • <a>标签去往的路由会重新渲染页面、可以使用_target="_blank"新打开一个标签页面
  • <router-link>可以进行replace操作

$route.matched

是一个数组,匹配当前的路由一级路由的祖父级

const routes = [
  {
    path: '/a',
    name: 'a',
    component: () => import("@/views/A.vue"),
    children: [
      {
        path: 'c',
        name: 'c',
        component: () => import("@/views/child/C.vue"),
      }
    ]
  },
]

访问'/a/c'时,matched如下 

问题

不同路由跳转到相同页面,缓存问题

现象:后台管理界面,存在二级路由,从'/home/a' 切换到 '/home/b' ,但当前这两个路由对应的是同一个页面组件,此时会出现缓存现象,第二次访问不会进行mounted之前周期的渲染。

//router.js
const routes = [
  {
    path: '/home',
    name: 'home',
    component: Home,
    meta: { static: true },
    // /a , /b 对印着同一个页面
    children: [
      { path: 'a', componentPath: 'views/child/A.vue' },
      { path: 'b', componentPath: 'views/child/A.vue' }]
  },
]

解决方法:

 1.在home的route-view标签中设置key,是vue-router认为这是两个不同的路由

<template>
  <div id="home">
    <div @click="pushRouter('/b')">点击跳转B</div>
    <div @click="pushRouter('/a')">点击跳转A</div>

    <router-view :key="$route.fullPath"></router-view>
  </div>
</template>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值