Vue路由自学笔记

利用#hash实现路由切换

注意利用了动态组件的思路,即标签,实现组件的动态切换,配合onhashchange事件对hasx地址改变监听,实现路由跳转
当点击不同的a链接的时候,对应的url地址的hash值就会跟着变化,同时事件监听到就执行对应的操作。

<template>
  <div class="App-container">
    <h1>这是App组件h1>
    <a href="#/home">首页a>
    <a href="#/body">主体a>
    <a href="#/footer">尾部a>
    <hr />
    <component :is="componentId">component>
  div>
template>
export default {
  name: "App",
  data() {
    return {
      componentId: "Home", //默认显示Home组件
    };
  },
  components: { Home, Body, Footer },
  mounted() {
    window.onhashchange = () => {
      switch (location.hash) {
        case "#/home":
          this.componentId = "Home";
          break;
        case "#/body":
          this.componentId = "Body";
          break;
        case "#/footer":
          this.componentId = "Footer";
          break;
      }
    };
  },
};

vue-router的理解

vue的插件库,专门用来实现SPA应用,即单个页面的应用。整个应用只有一个完整的页面。数据只是局部刷新,不会引起整个页面的刷新跳转。所以的数据都是通过ajax请求获取来的。
在之前的网页中实现路由功能是通过多页面的方式,即存在多个HTML后缀的文件,通过点击链接去实现不同页面的切换,但是这种切换路由的方法有一个缺点,就是整个页面都会被刷新,重新渲染,会造成页面的抖动。而在现在的路由中是单页面实现跳转。

路由

一个路由route对应一个路径,完整对应的事情。

  1. 后端路由
    *:在后端中处理路由的时候,通过匹配路由,执行对应的回调函数去实现效果、如express中,app.get(“/api”,()=>{}),在回调函数中处理需要响应的数据。
  2. 前端路由
    *:通过vue-router检测匹配的路由,然后去渲染对应的component组件。

vue-router介绍

vue-router是Vue提供专门处理路由的一个插件库,需要npm i vue-router@3安装vue2对应的才能使用的vue-router版本,默认安装vue3对应的vue-router4版本的。当安装完毕后,需要在入口文件中使用Vue.use(vue-router)使用路由。同时也需要配置vue-router相关的配置项。

// 引入vue-router插件
import VueRouter from 'vue-router'
// 使用插件库
Vue.use(VueRouter)

配置路由的相关信息

当引入了vue-router插件,并使用了该插件的时候,vue就为我们提供了一个全新的配置项router,该配置项在new Vue()的时候配置。
router配置项不向vuex中的store一样可以随意配置不报错,如下,给router配置项设置了一个字符串作为值,vue开发者工具直接给出报错提示,即router必须是一个函数,所以我们需要单独创建一个文件实现router函数的功能。
Vue路由自学笔记_第1张图片
以下是配置的路由文件,引入vue-router模块,即VueRouter,本质是一个构造函数,需要new实例化并配置路由的相关参数。
在VueRouter配置中提供了routes配置项,该配置项就是实现前端路由的主要参数。routes参数接收一个数组作为参数,数组的每一个参数均为一个路径配置对象,每一个配置对象可以设置path配置路径信息,当匹配成功的时候,就会渲染component配置项提供法组件,并去渲染。

import VueRouter from 'vue-router'
import Home from '../components/Home.vue'
import About from '../components/About.vue'
// 配置路由为一个数组对象,每一个对象包含配置项
const router = new VueRouter({
  routes: [
    {
      path: '/About',
      component: About
    },
    {
      path: '/Home',
      component: Home
    }
  ]
})
export default router

Vue路由自学笔记_第2张图片

当配置完这些步骤后,同样的还需要在HTML结构文件中设置vue-router提供的语法,将原先页面中a标签的调整改成如下代码
其中将所有的a标签改成vue-router提供的全新标签router-link,并将原先href实现跳转的属性改成to。这样子一个基本的路由就实现了,为了效果的完美实现,将active动态的提交给路由控制,即利用active-class动态的添加样式active。最终所有的router-link标签都会被解析成a标签显示,且都是由vue-router自动添加上了#符号。实现功能就和原先a链接中的href中手动添加#符号效果一致

    <a href="#/路径"></a>
    <router-link to="/路径"></router-link>
          <!-- 原始页面跳转 -->
          <!-- <a class="list-group-item" href="./about.html">About</a>
         	   <a class="list-group-item active" href="./home.html">Home</a> 
          -->
          
          <!-- vue-router跳转 -->
          <router-link class="list-group-item" active-class="active" to="/about"
            >About</router-link>
          <router-link class="list-group-item" active-class="active" to="/home"
            >Home</router-link>

在这里插入图片描述

设置完毕后还需要设置路由匹配成功的时候,即当匹配到/about路由的时候,需要将对应的组件显示在对应的位置。为此vue-router提供了新的标签router-view,即将匹配到的组件信息放在该标签的地方显示。

          <router-view></router-view>

这里配置的路由是前端路由,不涉及任何后端服务器,在浏览器的网络请求中就可以看出,没有任何请求发送。

路由配置的注意点

  1. 路由的组件分类
    *:一般的组件不需要经过路由配置处理显示的组件称为一般组件,即需要使用组件标签放在结构中的相关位置。通常这些组件是放在components文件夹中。
    *:路由组件即需要通过vue-router管理的路由,通常需要放在一个与components文件夹同级别的pages文件夹中。路由组件最重要的特点是不需要亲自使用组件标签,而是通过配置属性后,由路由决定将哪些组件放再router-view标签中显示。

  2. 路由组件的销毁问题
    *:所有通过路由管理的组件,当切换路由的时切换到其他组件的时候,原先组件默认是被销毁的(可以使用特殊方法),在成功配置路由的时候才会挂载。
    在路由组件中配置如下代码查看生命周期函数

  mounted() {
    console.log("home创建了");
  },
  beforeDestroy() {
    console.log("home被销毁了");
  },

Vue路由自学笔记_第3张图片

3: $route与$router属性
*:当成功配置完路由的时候,所有的路由组件实例都会多出两个属性,$route和$router。所有的路由组件中$route都是各不相同的。但是每一个$router都是相同的

在各个路由组件中配置如下代表即可验证

  window.aboutRoute = this.$route;
  window.aboutRouter = this.$router;
  window.homeRoute = this.$route;
  window.homeRouter = this.$router;

Vue路由自学笔记_第4张图片

路由重定向–redirect配置项

当某些时候访问到没有权限的路由的时候,会自动进行重定向操作。
如下代码中:当路径如http://www.localhost:8080的时候,会自动重定向到主页home。

  routes: [
    { path: '/', redirect: '/home' },
    { path: '/home', component: Home },
    {
      path: '/body',
      component: Body,
      redirect: '/body/item',
      children: [
        { path: 'item', component: Item },
        { path: 'item2', component: Item2 },
      ]
    },
    { path: '/footer', component: Footer },
  ]
默认子路由

在上诉代码中,在子路由中的重定向实现过程中,使用redirect重定向过于麻烦,所以这里使用默认子路由实现。
默认子路由:如果在children数组中,某个路由规则的path值为空字符串,则这条路由规则叫做默认子路由。
如下代码,当匹配到/body路由的时候,由于该路由的children配置项中存在默认子路由,所以又会去显示默认子路由中的组件信息。

    <router-link to="/body">显示的内容1</router-link>
    ----------------------------
    {
      path: '/body',
      component: Body,
      children: [
        { path: '', component: Item },
        { path: 'item2', component: Item2 },
      ]
    },

多级(嵌套)路由

多级路由在原先的基础上多配置一个children配置项,即告诉路由器这是一个子路由,在子路由同样接收一个数组对象,其中每一个对象接收的参数和routes的配置项一样,最重要的一点就是子路由中的path不需要添加‘/’符号,这一点和express中的子路由匹配不同。这是因为vue-router在运行的时候,检索到children配置项就知道这是一个子路由,于是在底层就会自动为我们的path路由添加上‘/’符号,如果我们错误的操作添加了‘/’符号,vue-router在匹配时候就无法正确的匹配到路由。

const router = new VueRouter({
  routes: [
    {
      path: '/about',
      component: About
    },
    {
      path: '/home',
      component: Home,
      // 配置多级路由
      children: [
        {
          path: 'news',
          component: News
        },
        {
          path: "messages",
          component: Messages
        }
      ]
    }
  ]
})

在router-link中的to需要填写完整的路径信息,即匹配到一级路由后再次去匹配其子路由。

<template>
  <div>
    <h2>我是Home的内容</h2>
    <ul class="nav nav-tabs">
      <li>
        <router-link
          class="list-group-item"
          active-class="active"
          to="/home/news"
          >News</router-link
        >
      </li>
      <li>
        <router-link
          class="list-group-item"
          active-class="active"
          to="/home/messages"
          >Message</router-link
        >
      </li>
    </ul>
    <router-view></router-view>
  </div>
</template>

在填写路由路径的时候也可以使用’/:id’进行占位

路由传参

动态路由概念

动态路由指的是:把hash地址可变的部分作为参数项,提高路由规则的复用性。
使用:作为占位符来接收这些动态的参数。

    <router-link to="/footer/1">尾部</router-link>
    <router-link to="/footer/2">尾部</router-link>
    <router-link to="/footer/3">尾部</router-link>
    ----------------------------
    //只需要定义一个/footer/:id即可实现规则
     { path: '/footer/:id', component: Footer },

在之前的代码基础上配置一个三级路由组件,在二级路由组件的基础上,将数据传递过去显示。
数据信息通过二级路由组件messages传递过去。

const router = new VueRouter({
  routes: [
    {
      path: '/about',
      component: About
    },
    {
      path: '/home',
      component: Home,
      // 配置多级路由
      children: [
        {
          path: 'news',
          component: News
        },
        {
          path: "messages",
          component: Messages,
          // 再次配置三级路由
          children: [
            {
              path: 'details',
              component: Details
            }
          ]
        }
      ]
    }
  ]
})

以下代码是数据存放在messages路由组件中的情况
Vue路由自学笔记_第5张图片

模拟静态数据传输,接下来就是如何实现数据的传递,先进行简单的数据传递。

在路由传递过程中有多种携带数据的方式,这里先使用简单的query格式携带数据,即get默认的携带数据方式。
key=value&key-value

 <router-link to="/home/messages/details?id=666&title=你好">{{ detail.title }}</router-link>

接收方如何接收传递来的数据,这就需要借助每一个路由组件身上都有的$route属性,且该属性是各不相同的。打印$route输出如下
当从二级路由携带参数跳转到三级路由的时候,在三级路由后打印其$route属性,其为一个对象,对应的path属性会接收路径信息(不带参数),其中query是接收传递来的参数,表现形式为一个对象。
Vue路由自学笔记_第6张图片
接收方接收数据显示的代码

  <ul>
    <li>消息编号:{{ $route.query.id }}</li>
    <li>消息标题:{{ $route.query.title }}</li>
  </ul>

模拟动态数据传输

字符串的格式传递参数信息

采用指令语法告诉vue这后面的代码需要执行JS语法,在字符串里面采取了模板字符串的语法

        <router-link :to="`/home/messages/details?id=${detail.id}&title=${detail.title}`">
          {{ detail.title }}
         </router-link
采用对象的格式传递参数

当采用对象传递数据的时候,需要采用指令语法去控制,让vue指定如何处理字符串中的内容,其中对象中必须包含两个参数,path告诉vue-router需要跳转的地址,query参数也是一个对象,在对象中配置需要传递的参数

 <router-link
        :to="{
            path: '/home/messages/details',
            query: {
              id: detail.id,
              title: detail.title,
            },
          }"
        >
     {{ detail.title }}</router-link
  >&nbsp;&nbsp;

命名路由

命名路由是在路由配置项中给添加name属性,其作用是简化路由跳转的写法
name配置项
当配置了name属性的时候,在实现路由跳转的时候就能极大的简化路径的写法

const router = new VueRouter({
  routes: [
    {
      name: 'About',//name名字可以自定义
      path: '/about',
      component: About
    },
    {
      path: '/home',
      component: Home,
      // 配置多级路由
      children: [
        {
          path: 'news',
          component: News
        },
        {
          path: "messages",
          component: Messages,
          // 再次配置三级路由
          children: [
            {
              name: 'Detail',
              path: 'details',
              component: Details
            }
          ]
        }
      ]
    }
  ]
})

在跳转三级路由的地方配置了name属性“Detail”,那么在需要匹配该路径且跳转到该组件的地方,都可以使用简写的方式。即在router-link中的to属性中添加name属性,即可跳转。当写这种方式的时候,只能写在指令语法to中

<router-link
          :to="{
            // path: '/home/messages/details',
            name: 'Detail',
            query: {
              id: detail.id,
              title: detail.title,
            },
          }"
        >
          {{ detail.title }}
</router-link>

路由携带params进行传递参数

在路由组件身上$route对象上,将参数全部存入params对象中,需要将在对应的路由组件中配置path路径中配置占位项,如/home/4,其中4就是通过占位符获取的数据。

当需要使用params传递参数的时候,在路径中需要进行修改,将需要传递的值直接拼接在路径后面,这里需要注意的是,原来的路径不能省略即那些一级路径至三级路径
当路由进行匹配的时候,匹配到details路径的时候会自动将后面的666与占位符:id组成一个对象中的属性即id:666,最终将这些属性存入params对象中
Vue路由自学笔记_第7张图片

 <router-link :to="`/home/messages/details/666/dds`">
         {{ detail.title }}
 </router-link>

Vue路由自学笔记_第8张图片
当采用对象式传递params参数的时候如何写,只需要改动router-link中的即可
这里需要注意的是:当使用to对象格式传递params参数的时候需要将原先的query配置该为params配置,并且使用params的时候只能与name命名路由配合使用,无法与path参数配合使用,否则报错

<router-link
          :to="{
            name: 'Detail',
            params: {
              id: detail.id,
              title: detail.title,
            },
          }"
        >
          {{ detail.title }}
 </router-link>

注意点
Vue路由自学笔记_第9张图片

//路由如下
  <router-link to="/footer/1?name=zq">尾部</router-link>

Vue路由自学笔记_第10张图片

路由的props配置

引入路由参数rops的原因:当传递多个参数接收的时候,可能会重复的编写多个代码,这个时候就需要使用路由props配置项处理了。如下红色部分就是会重复多余的代码。
在这里插入图片描述

props配置

谁接收参数,就给哪一个路由组件添加props配置项。
props有三种写法

  1. 对象式写法,给props配置项配置一个对象,在该对象中配置需要传递的参数,所有的参数都会以props的形式传递给使用该参数的组件,在组件中以props配置项接收使用
    但是这种直接写一个对象的形式只能传递固定的值,写法单一,不推荐
传递参数
props: {
       id: '666',
       title: 'Vue'
      }

使用传递的参数

  props: ["id", "title"],
  1. 直接给props赋值布尔值
    当路由配置项中props的值为布尔值的时候,就会把该路由组件收到的所有params参数,以props的形式传递给使用该参数的组件
路由配置
 props: true

接收参数

  props: ["id", "title"],

一定需要注意这种布尔值的配置形式不能处理query传递参数的情况
Vue路由自学笔记_第11张图片

  1. props配置为函数式
    配置为函数写法,函数默认会接收一个$route对象作为参数,由vue-router自动帮我们去执行调用并传递参数。该函数的返回值为一个对象,在对象中可以随意的使用query或params中的参数进行传递,接收以props接收。
    Vue路由自学笔记_第12张图片
 props($route) {
   return { id: $route.query.id, title: $route.query.title }
}

接收并使用参数

  props: ["id", "title"],
 props($route) {
	return { id: $route.params.id, title: $route.params.title }
}

当然,如果想代码更加精简,可以在接收$route的时候就对该对象进行解构赋值
Vue路由自学笔记_第13张图片

router-link标签中的replace属性

replace作用:控制路由跳转时操作浏览器历史记录的模式。
如果不给router-link标签添加replace属性,则默认为push模式,即压栈,push是不断的往里面追加历史记录,而replace是替换历史记录。
:replace="true"replace两种写法
在这里插入图片描述

编程式路由导航

上面使用实现路由跳转的属于声明式路由导航,对标普通网页中的a链接。

现在所学的路由跳转是通过router-link标签实现跳转的,并且该标签最终会转换为a标签。那么如何给其他标签绑定路由跳转。
这个时候就需要借助$router属性了,该属性的原型链存放了帮助我们进行路由跳转的方法。
Vue路由自学笔记_第14张图片
这里我们需要使用$router身上的push方法和replace方法,其作用和在页面中使用router-link/to的作用是一致的,区别只是采取什么操作进行历史记录在push/replace方法中,参数和to参数的写法一致

        <button @click="pushShow(detail)">push操作</button>
        <button @click="replaceShow(detail)">replace操作</button>
  methods: {
    pushShow(detail) {
      this.$router.push({
        name: "Detail",
        params: {
          id: detail.id,
          title: detail.title,
        },
      });
    },
    replaceShow(detail) {
      this.$router.replace({
        name: "Detail",
        params: {
          id: detail.id,
          title: detail.title,
        },
      });
    },
  },

pushreplace的区别是:push方法类似栈的结构,符合浏览器中历史回退的前进和后退操作。而replace方法每次有新地址进入,都会覆盖上一个地址。

同时,在$router对象原型链上还有三个方法,分别为:back,forward,go其中back和forward方法实现的效果和浏览器的前进后退效果一致,且不需要传入参数。go方法需要指定传入的数字,正数代表前进几步,负数代表回退几步。

  methods: {
    forward() {
      // 实现浏览器前进效果
      this.$router.forward();
    },
    back() {
      // 实现浏览器回退效果
      this.$router.back();
    },
    go() {
      this.$router.go(-2); //前进两下
    },
  },

缓存路由组件

作用:在切换组件的时候,让原先的组件保持挂载不被销毁。
使用keep-alive标签**包住router-view标签。**为什么需要包裹router-view标签,是因为那些最终需要缓存的组件,都是被存放在该标签中显示的。
keep-alive标签中的include属性。如果不添加该属性,则默认在router-view标签中的所有展示的组件,在切换的过程中均不会被销毁而是缓存,但是通常并不是所以的组件都需要被缓存。
include="组件中的name值,即组件名"指定值的时候,即指定了哪些组件才需要被缓存。
Vue路由自学笔记_第15张图片
如果有多个组价,但是需要缓存其中的几个组件,就需要在include属性后面赋数组作为值。同时需要使用指令语法,告诉vue后面字符串中的值需要按照JS的语法去解读。

    <keep-alive :include="['News', 'Messages']">
      <router-view></router-view>
    </keep-alive>

使用keep-alive标签的最大作用是:当有一些输入框的时候,在其中输入了值,但是不希望切换组件的时候这些内容被销毁了。这时候就需要借助keep-alive标签缓存组件了。

路由新增的生命周期钩子函数

作用:路由组件独有的生命周期函数,用于捕获路由组件的激活状态。
activated生命周期函数deactivated生命周期函数
activated生命周期函数:用于组件被激活的时候触发
deactivated生命周期函数:用于组件失活的时候触发

引入这两个新的生命周期钩子的原因是:在原先的基础中,将定时器存放在mounted生命周期函数中,然而在路由组件的切换过程中会出现一个问题,就是当切换组件的时候,该组件被缓存了,随即定时器也会被暂停。但是这个效果在mounted函数和beforeDestroy生命周期函数中无法实现。因为这两个函数只针对组件被销毁,而缓存不属于这两个函数的范畴内。
以下是基于moutedbeforeDestroy生命周期函数实现的清除定时器效果,发现从News组件切回Messages组件,定时器无法清除
Vue路由自学笔记_第16张图片

Vue路由自学笔记_第17张图片

当使用activateddeactivated生命周期函数实现定时器效果就可以完成想要的结果

  activated() {
    this.timer = setInterval(() => {
      console.log("@");
      this.opacity -= 0.01;
      if (this.opacity <= 0) {
        this.opacity = 1;
      }
    }, 16);
  },
  deactivated() {
    console.log("News销毁");
    clearInterval(this.timer);
  },

Vue路由自学笔记_第18张图片

全局前置路由守卫

路由守卫的作用:在每一次切换路径的前后时间段,作出相应的操作。如路径判断是否放行等。
配置路由守卫应该是所有的路径都会进行相应的操作,所以需要放在router身上。

利用实例化完的vue-router,配置路由守卫。在router身上提供了beforeEach方法,beforeEach方法会在初始化的时候和路由切换前的时候执行,该方法接收三个参数分别为:to,from,next
to:Router 即将进入的目标路由对象
from: Router当前导航离开的路由,即上一个路由对象
next:为函数,调用该方法,即可放行,类似express中的中间件next放行

const router = new VueRouter({ ... })
全局前置路由守卫
router.beforeEach((to, from, next) => {
  console.log(to, from)
})

通过打印tofrom发现结果如下,于是我们就可以利用里面的参数;来决定是否放行。
Vue路由自学笔记_第19张图片
以下这段代码实现了如图所示的功能

// 配置全局前置路由守卫
router.beforeEach((to, from, next) => {
  // 如果进入的是子路由查看详细信息,就进行本地存储判断
  if (to.path === '/home/news' || to.path === '/home/messages') {
    if (localStorage.getItem('name') === 'admin') {
      next()
    } else {
      alert('错误信息!')
    }
  } else {
    next()
  }
})

Vue路由自学笔记_第20张图片

但是这么写有一个问题,就是当路径判断变多的时候,在if判断中就会写很长的代码,这不是理想的结果,所以,vue-router为我们提供了每一个路由都独有的meta配置项,在该配置项中可以决定哪些路径是否进行权限控制
提供meta配置项的初衷是为了可以在路由中配置自己的信息,但是如果直接配置在配置对象中vue-router不会对该属性进行处理。所以meta配置项的作用就体现出来。将所有自己的信息存入meta元信息中保存。
Vue路由自学笔记_第21张图片
Vue路由自学笔记_第22张图片

全局后置路由守卫

全局后置路由守卫也是使用router路由器提供的afterEach方法。该方法在路由改变之后进行相应的操作,只要路由没有发生跳转就不会被执行afterEach方法只接收两个参数即tofrom,(接收的参数和前置路由守卫一样),接收的参数数量和前置路由守卫不同,不需要next的原因是,后置路由守卫在路由切换后才进行操作,这个时候就不需要next函数进行放行操作了。
添加一个需求,即每次页面切换的时候,切换网页的标题。提前将自定义的数据存放在meta元信息中。

在这里插入图片描述
在前置路由中配置代码解决此问题,但是还是会有一个问题,就是当页面在localhost:8080的时候,不断的刷新回发现标题会在vue_router_01test和首页之间来回切换。这个问题可以在index.html中修改默认的title显示。但是这种操作麻烦,所以全局后置路由就出现了。

router.beforeEach((to, from, next) => {
  // 如果进入的是子路由查看详细信息,就进行本地存储判断
  if (to.meta.isAuth) { //进行路由权限校验
    /* 放在这里为时过早,如果本地存储判断失败则显示上一个的title,而
    这里会提前显示 */
    // document.title = to.meta.title 
    if (localStorage.getItem('name') === 'admin') {
      document.title = to.meta.title
      next()
    } else {
      alert('错误信息!')
    }
  } else {
    document.title = to.meta.title || '首页' //初始化没有路径信息即title为undefined
    next()
  }
})

将所有对标题的操作全部放在后置路由中

// 配置全局前置路由守卫
router.beforeEach((to, from, next) => {
  // 如果进入的是子路由查看详细信息,就进行本地存储判断
  if (to.meta.isAuth) { //进行路由权限校验
    if (localStorage.getItem('name') === 'admin') {
      next()
    } else {
      alert('错误信息!')
    }
  } else {
    next()
  }
})

// 配置全局后置路由守卫
/* 当路由跳转失败的时候,后置路由不会走
所以页面标题就显示上一次的标题 */
router.afterEach((to, from) => {
  console.log("后置")
  document.title = to.meta.title || '首页'
})

独享路由守卫

独享路由守卫即局部的路由守卫,只针对某一个路径进行相应的操作。
独享路由守卫只有前置路由没有后置路由,这是一个重点需要记忆的地方。需要用到后置路由处理的东西全局后置路由即可完成效果。
beforeEnter独享路由的守卫方法,该方法的作用是全局前置路由守卫作用一致,即在路径切换前进行处理,也是接收三个参数分别为to,from,next
Vue路由自学笔记_第23张图片

组件内路由守卫

顾名思义,即在组件内部使用路由守卫。
beforeRouterEnter(to,from,next)方法,该方法当匹配路由规则后允许进入组件前调用。这个时候不能获取this实例,因为守卫执行的前,组件实例还没有被创建。
beforeRouterLeave(to,from,next)方法,离开该组件的时候,该方法会被调用。这个时候可以访问this
注意这里的组件内路由守卫和全局前置后置路由守卫的区别。在全局前置后置路由中,一旦匹配成功后,则全局前置与后置路由都会执行。而组件内的路由守卫不会,特别注意beforeRouterLeave方法,当匹配路由成功的时候进入该组件,只有beforeRouterEnter方法会被调用,当切换路由的时候从当前组件离开的时候,beforeRouterLeave方法才会被执行。
下图所示,当匹配路由规则进入后,只有beforeRouterEnter方法执行。
Vue路由自学笔记_第24张图片
当离开组件的时候进入其他组件,beforeRouterLeave方法就会被调用
Vue路由自学笔记_第25张图片

注意:匹配路由规则的含义,如果直接在页面中使用该组件的组件标签,则不属于路由范畴,所以并不会去执行beforeRouterEnter方法。
Vue路由自学笔记_第26张图片

路由器的history和hash模式

在默认的服务器环境下,我们打开了某一个路径显示的页面,会发现在url中总是包裹着一个‘#’符号,这个就是前端所说的hash,一旦是hash模式,那么‘#’符号后面的所有路径信息不会出现在HTTP请求中,即不会被发送给服务器
在这里插入图片描述
history模式,即不带’#'符号的正常路径
在vue-router中默认为hash模式,如果想修改为history模式,则需要在路由器的实例中设置配置项mode,
mode配置项的默认值为hash,可以修改为history
Vue路由自学笔记_第27张图片

那么hash模式和history模式的区别:首先history的路径看起来舒服,其次hash模式在低版本的浏览器中兼容性好。且涉及到项目打包上线服务器的相关操作使用hash模式方便。

项目打包上传服务器

浏览器只认识html,css,js文件,所有的vue编写的文件最终都需要打包才会生成浏览器能认识的文件。
这个时候package文件中提供的命名操作就起作用了。serve是运行脚手架环境的服务器,而build是将写好的vue文件打包为浏览器能认识的文件。
在这里插入图片描述

npm run build 

当打包完成后,项目文件中会多次一个文件夹dist,其中存放这打包后的vue文件。但是个index.html文件是无法打开的,这些文件必须部署在服务器后才能打开
Vue路由自学笔记_第28张图片

  1. 当vue-router的模式为hash的时候

当vue-router的模式为hash的时候,将生成的dist文件部署在服务器的静态文件中,查看效果,在index.html页面中点击任何按钮都不会发送网络请求。
hash模式下最大的特点是:当进入某一个路由的时候,地址如:http://localhost:5050#/home,一旦刷新页面,不会报错404,页面能够正常显示,(服务端设置的静态资源文件名index.html,localhost:5050默认打开该文件,前提文件名必须为index)这是因为#符号及其后面的内容都不会随着HTTP请求发送给服务器处理

  1. 当vue-router的模式为history模式的时候

当vue-router的模式为history模式的时候,将生成的文件部署到服务器的静态文件夹中,查看效果
初始的时候打开静态文件index.html,在里面点击进行切换进入到http://localhost:5050/home的路径中。随机点击刷新,会发现页面出现错误,无法正常显示。
原因是:当从index.html路径进入到http://localhost:5050/home路径的时候,没有发送任何网络请求,所以服务器不会处理,一旦重新刷新,那么就将该路径进行HTTP请求发送给服务器,而服务器中无相关的/home文件路径,所以就报错
Vue路由自学笔记_第29张图片
服务器端只响应/api路径的请求
在这里插入图片描述
Vue路由自学笔记_第30张图片
如何解决此问题,vue2官网中推荐使用 connect-history-api-fallback 中间件

  1. npm i connect-history-api-fallback 安装该中间件
  2. const history = require('connect-history-api-fallback')引入该中间件
  3. app.use(history())使用该中间件提供的方法,一定需要在定义静态文件夹前使用
    按照上面的步骤执行完毕后,那么在history模式下刷新也能正常显示页面。

你可能感兴趣的:(vue.js,前端)