vue-route详细介绍 (上)

简介: vue-route详细介绍 (上)
  1. 前后端路由的来历


  1. 前端如何实现页面跳转但是不刷新?


  1. 了解hash和history两种方法


  1. vue-router基本使用


  • 安装vue-router
  • 搭建vue-router框架的步骤
  • vue-router路由的配置步骤
  • 第一步: 创建路由组件
  • 第二步: 配置路由映射。 即:组件和路由的关系
  • 第三步: 使用路由, 通过和来展示组件


  • 路由的默认配置
  • 修改静态路由的模式为history
  • vue-link属性设置
  • 通过代码跳转路由
  • 动态路由的使用
  • 路由的懒加载


  1. vue-router的嵌套
  2. vue-router参数传递
  3. vue-router导航守卫
  4. keep-alive

说道路由, 我们最熟悉的路由是什么呢? 那就是路由器了。 其实路由器有两个重要的功能: 路由和传送


  • 路由: 路由决定数据包从哪里来, 到哪里去。 也有是来源和目的地的路径。
路由中有一个路由表, 路由表本质上就是一个映射表,决定了数据包的传输方向。
  • 传送: 传送是将输入端的数据传送给输出端


下面我们先来搭建一个项目, 然后一边学习一遍在项目里实战

创建vue-cli2项目

vue init webpacek vueroute

然后一路向下就可以了, 如果本地创建项目很慢, 可以采用离线创建项目的方式, 具体步骤:

  1. 下载webpack离线模板: https://github.com/vuejs-templates/webpack
  2. 将下载的模板压缩包解压,修改文件名为wepback并放入到/Users/自己电脑的用户名/.vue-templates文件夹中.
  3. 执行创建项目的命令: vue init webpack --offline


一. 前后端路由的来历



前后端路由, 目前经历了三个阶段, 哪三个阶段呢?


  1. 前后端一体(后端路由)阶段: 这个阶段类似早起的jsp页面, 和java页面混合在一起, jsp里面有css, js, 还有java代码, 前后端都是混合在一起的.


缺点很明显, 前后端分工不明确.


  1. 这种方式采用的是后端路由


基本流程: 请求一个controller接口 --> 通过接口找到页面 --> 渲染页面 --> 返回给浏览器


  1. 前后端分离阶段: 前端通过ajax调用的形式, 调用后台接口. 前端主要负责页面渲染, 后端主要提供api接口.


优点: 前后端分离. 各司其职, 分明明确. API可复用性强, fe, android, ios都可用


  1. 此时用户请求的就是一个html页面, 页面需要哪个url了, 直接通过ajax请求到页面.


基本流程: 浏览器url请求 -> html页面 -> ajax请求api接口 -> 后台接口响应数据 -> html页面渲染 -> 返回给浏览器


  1. 单页面富应用阶段: 简称SPA, 全称是simple page application. 最主要的特点是在前后端分离的基础上加了一层前端路由. 这个路由是有前端来维护的一套路由.


单页面指的是:一个html文件 + 一个js文件 + 一个css文件.


可是就一个网站来说, 不可能只有一个页面. 那么是如何实现的呢?我们来看下图

e130a74574b34785a6cd91c5249dff04_tplv-k3u1fbpfcp-watermark.png

前端只有一个页面index.html, 而各个功能都是一个组件, 将所有组件都放到index.html页面中, 然后根据用户的请求定位到某一个组件. 这个是谁来定位的呢?就是前端路由来定位, 在vue中前端路由就是vue-router.


前端路由的核心是什么呢? 改变url, 但是页面不进行整体刷新.


二. 前端如何实现页面跳转但是不刷新?



前面说了, vue使用的是单页面富应用, 也就是一个index.html就是整个项目, 然后在内部在跳转链接的时候, 不会刷新页面, 实现这种方式有两种方法:hash和history

这两种模式都可以实现页面跳转,但是不刷新页面. 他们如何使用, 又有什么区别呢?


1. hash


首先启动vue项目


vue init dev


然后打开页面


localhost:8080


在浏览器控制台输入localhost.hash="about", 我们可以看到页面链接变成了localhost:8080/#/about/


image.png

如上图, 我们可以通过location.hash="链接"的方式来修改url,但是并不刷新页面


2. history


除了使用hash,我们还可以使用history来改变实现改变url但不刷新页面的方法. history有几个常见的用法.


  1. history.pushState(state,"title","url")
    向浏览器新增一条历史记录,但是不会刷新当前页面(不会重载)


  • state为对象,可以用作携带信息用,
  • title:目前来看没啥用一般为空或null,
  • URL:即要更改页面的URL,且必须同源,不能跨域;


案例: 我们在vue的浏览器界面改变http://localhost:8080为http://localhost:8080/about


image.png

如上图所示: 当我们执行history.pushState({a:1},null,"about");的时候, 浏览器并没有刷新页面(Network没有请求), 但是url链接确实发生了变化


  1. history.replaceState(state,title,URL)


更改当前浏览器的历史记录,即把当前执行此代码页面的记录给替换掉,参数与第一条相同


  1. history.back()、history.forward()、history.go()
    分别为前进一个历史,后退一个,history.go(Number),其中Number可正可负,即向前或向后若干个记录


案例:

image.png



如上图, 当我们使用history.back()命令的时候, 会回退到上一个页面, 也并没有发生更新.

  1. history.state
    返回当前页面状态参数,此参数一般由history.pushState(state,title,URL);以及history.replaceState(state,title,URL);附带的state值,例子如下:

案例:

image.png


如上图: 可以看出history.state就是取出了pushState和replaceState两个命令中的第一个参数

  1. history.length
    返回当前页面所产生的历史记录个数,即在同一个浏览器tab下产生的历史记录;
  2. history事件onpopstate
window.onpopstate = function(e){
  console.log(e.state);
}

在history.back(),history.forward(),history.go()时触发此事件,但是在history.pushState();history.replaceState();时并不会触发此事件,事件内可以获取到state状态值


可以看出vue-router中push()、go()等函数是基于hash和histroy的,但是vue-router比这个要复杂.


三. vue-router基本使用



vue-router是Vue.js官方的路有插件, 他和vue.js是深度集成的.适合构建于单页面富应用.

vue-router官网: https://router.vuejs.org/zh/

  • vue-router是基于路由和组件的: 路由用于设定访问路径, 将路径和组件映射起来
  • 在vue-router的单页面应用中, 页面的路径的改变就是组件的切换.


1. 安装vue-router


npm install vue-router --save

--save: 表示在构建以后也要使用这个路由

安装好以后, 在package.json中就可以看到安装的vue-router的版本了

82be3438e89240f989714b79d74e100f_tplv-k3u1fbpfcp-watermark.png


并且在src目录下多了一个文件夹router

225e5ff1bbda4f71972396a43898de07_tplv-k3u1fbpfcp-watermark.png


2. 搭建vue-router框架的步骤


在我们安装了vue-router以后,就会在src目录下自动生成一个文件夹router.

我们在里面创建一个index.js文件, 然后开始配置路由相关的信息


  • 第一步: 导入路由对象,并且调用vue.use(VueRouter)
    安装了vue-router, 要想使用, 还需要先引入路由对象
import Router from 'vue-router'

vue-router是一个插件, 所以, 我们需要使用vue.use(插件名) 来安装插件

Vue.use(Router)
  • 第二步: 创建路由实例,并且传入路由映射配置
  • 在VueRouter中主要是配置路由和组件之间的映射关系的.


const routes = [
]
const router = new VueRouter({
  // 这里配置的是路由和组件的映射关系, 是一个数组.
  routes
})

在这里路由是空的, 还没有配置任何映射关系.


  • 第三步: 将vue-router实例对象导出
export default router
  • 第四步: 在vue实例中挂载创建的路由实例


import router from './router'

在import目录的时候, 有一个默认的规则, 那就是如果你导入一个目录, 比如./router, 没指定导入哪一个文件, 他会自动导入index.js文件*


然后在vue实例中引入router


new Vue({
  el: '#app',
  // 然后通过router导入vue路由
  router,
  render: h => h(App)
})

3. vue-router路由的配置步骤


  • 第一步: 创建路由组件
    通常, 我们会在components目录下创建组件。鼠标右击-> Vue Component, 然后定义组件内容
    我们创建两个组件, 一个首页, 一个关于页面.


首页

<template>
 <div>
   <h2>这是Home主页</h2>
   <div>欢迎来到home主页</div>
 </div>
</template>
<script>
   export default {
       name: "Home"
   }
</script>
<style scoped>
</style>

关于页面

<template>
 <div>
   <h2>关于页面</h2>
   <div>欢迎来到关于页面</div>
 </div>
</template>
<script>
   export default {
       name: "About"
   }
</script>
<style scoped>
</style>

这样组件就创建好了。


  • 第二步: 配置路由映射。 即:组件和路由的关系

组件创建好了, 接下来要构建组件和路由的关系。 构建路由关系,我们通常定义在router/index.js文件


映射关系主要有两个部分. 一个是path:路由的路径; 一个是component:关联的组件

在router/index.js文件中首先引入上面定义好的组件


import Home from '../components/Home';
import About from "../components/About";

然后指定路由路径和组件


const routes = [
  {
    path: "/home",
    component: Home
  },{
    path: "/about",
    component: About
  }
]
  • 第三步: 使用路由, 通过和来展示组件
    现在组件有了, 路有关系也有了。 那么接下来就是要有个入口来展示组件或者路由了。 我们的入口只有一个, 那就是App.vue, 所以, 我们直接在这里定义两个入口即可。


<template>
  <div id="app">
    <!-- 定义两个路由链接 -->
    <router-link to="/home">首页</router-link>
    <router-link to="/about">关于</router-link>
    <!-- 展示组件内容 -->
    <router-view></router-view>
  </div>
</template>

: 是一个vue-router中内置的组件, 它会被渲染成一个a标签。

: 会根据当前的路径, 动态渲染组件的内容

网页的其他内容, 例如:顶部的标题/导航,底部的版权信息等和/处于一个等级

在切换路由时, 切换的是挂在组建的内容, 其他不会发生改变

整体效果如下:


image.png

4. 路由的默认配置


现在我们进入首页显示的只有导航信息, 在页面必须点击某一个按钮,才能渲染出对应组件的内容。通常我们会有一个默认组件的展示。 否则首页内容就是空的了。如何设置默认展示的路由呢?


在路由表中增加一个重定向路由


{
    path:"/",
    redirect: "/home"
}

这样, 打开首页,直接加载home组件的内容


5. 修改静态路由的模式为history


我们之前都是采用hash的方式来静态路由跳转的, 但hash方式有一个缺点, 即带有#

例如:我们跳转都Home页, 他的路径是


http://localhost:8080/#/home

带有一个#, 这不符合我们通常路径的使用方法,所以,我们可以考虑将其替换为history的模式。 如何替换呢? 在router/index.js文件中

const router = new Router({
  // 这里配置的是路由和组件的映射关系, 是一个数组.
  routes,
  mode: "history"
})

6. vue-link属性设置


1. to属性


我们在首页, 定义vue-link跳转的路由使用的就是to属性


<template>
  <div id="app">
    <!-- 定义两个路由链接 -->
    <router-link to="/home">首页</router-link>
    <router-link to="/about">关于</router-link>
    <!-- 展示组件内容 -->
    <router-view></router-view>
  </div>
</template>

2. tag属性


默认会被渲染成a标签, 如果我们想要将其渲染为其他标签是否可以呢? 当然是可以的, 使用tag属性, 比如: 我们想要将其渲染为button标签


<template>
  <div id="app">
    <!-- 定义两个路由链接 -->
    <router-link to="/home" tag="button">首页</router-link>
    <router-link to="/about" tag="button">关于</router-link>
    <!-- 展示组件内容 -->
    <router-view></router-view>
  </div>
</template>

image.png

3. replace属性

如下图, 我们在点击导航以后, 可以在浏览器向前或向后导航

image.png

如果我们不想要浏览器记录我们的请求行为, 可以使用replace. 我们只需要在标签中增加属性replace就可以了. 这个属性不需要设置值

<template>
  <div id="app">
    <!-- 定义两个路由链接 -->
    <router-link to="/home" tag="button" replace>首页</router-link>
    <router-link to="/about" tag="button" replace>关于</router-link>
    <!-- 展示组件内容 -->
    <router-view></router-view>
  </div>
</template>


效果如下: 浏览器的返回和前进按钮都不可用


image.png

4. active-class 修改激活时样式名称的默认值

先来看看如何设置元素的样式.

在点击按钮的时候, 在控制台可以看到有一个样式router-link-active, 这个样式是控制按钮激活的样式, 如果我们想要修改激活的效果, 修改这个样式即可.


image.png

比如: 我们设置按钮激活时字体颜色为红色.


<template>
  <div id="app">
    <!-- 定义两个路由链接 -->
    <router-link to="/home" tag="button" replace>首页</router-link>
    <router-link to="/about" tag="button" replace>关于</router-link>
    <!-- 展示组件内容 -->
    <router-view></router-view>
  </div>
</template>
<script>
export default {
  name: 'App'
}
</script>
<style>
.router-link-active {
  color:red;
}
</style>


重点看style里面的样式定义. 效果如下:


image.png

router-link-active是vue-router默认/激活时显示的样式, 如果想要修改这个样式名称, 可以使用active-class.


<template>
  <div id="app">
    <!-- 定义两个路由链接 -->
    <router-link to="/home" tag="button" replace active-class="active">首页</router-link>
    <router-link to="/about" tag="button" replace active-class="active">关于</router-link>
    <!-- 展示组件内容 -->
    <router-view></router-view>
  </div>
</template>

如上, 可以看到active-class="active", 表示将默认的属性重命名为active.

后面重定义样式的时候, 使用active即可


<style>
.active {
  color:red;
}
</style>

全局修改active-clas的默认名称. 可以在路由里实现.


修改router/index.js文件


const router = new Router({
  // 这里配置的是路由和组件的映射关系, 是一个数组.
  routes,
  mode: "history",
  linkActiveClass: "active"
})


7. 通过代码跳转路由


上面我们都是在vue中直接使用来路由, 我们还可以使用普通标签路由, 例如button标签, 来看看怎么实现


第一步: 定义两个button元素


<template>
  <div id="app">
    <!-- 定义两个路由链接 -->
    <button @click="clickHome">首页</button>
    <button @click="clickAbout">关于</button>
    <!-- 展示组件内容 -->
    <router-view></router-view>
  </div>
</template>

这就是两个普通的button, 然后定义了两个click点击事件, 下面我们就要在点击事件中实现路由

第二步: 定义click事件, 路由到组件

<script>
export default {
  name: 'App',
  methods:{
    clickHome() {
      this.$router.push("/home")
      console.log("点击home按钮")
    },
    clickAbout() {
      this.$router.push("/about")
      console.log("点击about按钮")
    }
  }
}
</script>

这里定义了点击事件. 通过this.$router.push("/home")来路由到home组件.


this.$router.push("/home"): 在每一个vue对象中, 通过this都可找到$router属性, 这是一个全局的属性.

this.$router.push("/home")是使用history的的方式路由到对应的组件, 可以通过浏览器的前进和后退按钮路由.

this.$router.replace("/home"): 不可以使用浏览器的前进和后退按钮路由.


8. 动态路由的使用


动态路由是什么概念呢? 通常我们的url是不变的, 比如. /home, 有些url是变化的,比如/user/zhangsan, /user/lisi, 对于变化的url, 我们如何路由呢?


下面就以用户为例, 来实现动态路由


第一步: 创建一个User.vue模板

<template>
    <div>
      <h2>用户界面</h2>
      <div>欢迎你来到用户界面</div>
    </div>
</template>
<script>
    export default {
        name: "User"
    }
</script>
<style scoped>
</style>

第二步: 添加路由映射关系


import User from "../components/User"
const routes = [
  {
    path: "/user/:userId",
    component: User
  }
]

这里path使用了:userId占位, 表示这里是一个占位符, 将被真实的userId替换. 后面在路由传递的时候变量需要和这里保持一致.


第三步: 使用user路由


当我们动态路由到user的时候, 需要使用变量userId, 我们可以在data中定义一个变量

<template>
  <div id="app">
    <!-- 定义两个路由链接 -->
    <router-link to="/home" tag="button" replace active-class="active">首页</router-link>
    <router-link to="/about" tag="button" replace active-class="active">关于</router-link>
    <router-link v-bind:to="'/user/'+userId" tag="button" replace active-class="active">用户</router-link>
    <router-view></router-view>
  </div>
</template>
<script>
export default {
  name: 'App',
  data(){
    return {
      userId:"zhangsan"
    }
  }
}
</script>

在上面使用了v-bind:to="'/user/'+userId"路由到/user/:userId, 而userId是我们在组件中定义的一个变量.


第三步:来看看效果


image.png


我们看到当点击用户的时候, 浏览器的url路径变为了/user/zhangsan.

第四步: 将参数传递到组件


我们希望在user组件中显示, 欢迎{{用户名}}来到用户页面, 如何实现呢?


要想实现这个效果, 需要使用到this.$route对象. 这是获取路由信息的对象.

<template>
    <div>
      <h2>用户界面</h2>
      <div>欢迎{{userId}},来到用户界面</div>
    </div>
</template>
<script>
    export default {
        name: "User",
        data(){
          return {
            userId:this.$route.params.userId
          }
        }
    }
</script>
<style scoped>
</style>

可以看到在data属性中,我们通过this.$route.params.userId 获取到了路由连接中的userId参数.


然后在页面通过语法糖的方式展示出用户{{userId}}即可.


来看看效果:


image.png

如上图所示, 我们看到userId变量被传递到了组件里面.

这里重点想要说的就是通过this.$route.params获取变量.

我们也可以在页面直接使用{{$route.params.userId}}获取路由参数


<template>
    <div>
      <h2>用户界面</h2>
      <div>欢迎{{userId}},来到用户界面</div>
      <div>{{$route.params.userId}}</div>
    </div>
</template>

9. 认识路由的懒加载


首先为什么需要懒加载, 原因是, 当我们打包的时候, 会将所有的js文件,css进行打包, 打包到一个文件中, 然后在index.html页面中引入这些js,css文件.我们来看一下效果

首先, 我们先将项目打包, 然后看看打包后的文件结构


npm run build

打包完成以后, 会生成一个dist的文件夹,里面就是打包后的文件

d5264478ce87444aa7797ffab176e103_tplv-k3u1fbpfcp-watermark.png


如上图文件结构如下:


有一个index.html文件和static文件夹


  • index.html: 项目的主页面入口
  • static文件夹: 存放的是css和js等静态资源
  • css文件夹: 里面只有一个app.*.css文件, 这个文件是将所有的css整合到这里了
  • js文件夹: 该文件夹中有三个文件
  • app.*.js: 这个文件整合的是我们自己写的业务逻辑相关的js代码
  • manifest.*.js: 这个文件整合的是支撑我们的业务逻辑的底层支撑js代码
  • vendor.*.js: 这个文件整合了使用到的所有外部组件的js代码


一个项目可能有很多组件, 有自定义的组件, 有引入的外部组件, 那就会有很多js, css代码, 最终全部通过index.html加载进来, 这样在首次加载的时候速度就会很慢. 所以, 我们需要使用懒加载, 来提高首次加载速度.


什么是懒加载呢?


使用时才加载, 就是懒加载, 而不是一次性全部加载进来

怎样才能做到懒加载呢?


把不同的路由对应的组件分隔成不同的代码块, 而不是统一全部加载到app.*.js文件中,当路由被访问的时候才加载对应的js文件, 这样会更加高效

如何实现懒加载呢?


在路由定义的时候, 是有懒加载的方式


原来定义路由是这样的

import Home from '../components/Home';
import About from "../components/About";
import User from "../components/User"
/*
 * 第一步: 安装插件
 * vue-router是一个插件, 所以, 我们需要使用vue.use(插件名) 来安装插件
 */
Vue.use(Router)
/*
 * 第二步: 构建VueRouter对象
 * 在VueRouter中主要是配置路由和组件之间的映射关系的.
 */
const routes = [
  {
    path:"/",
    redirect: "/home"
  }, {
    path: "/home",
    component: Home
  },{
    path: "/about",
    component: About
  },{
    path: "/user/:userId",
    component: User
  }
]

懒加载需要使用一个匿名函数来import, 表示使用的时候在import引入. 一个懒加载在打包的时候会单独打包成一个js文件.


// 这里会引入你要导入的组件, 然后通过路由配置组件内容
const Home = () =>import('../components/Home');
const About = () => import('../components/About');
const User = () => import('../components/User');
/*
 * 第一步: 安装插件
 * vue-router是一个插件, 所以, 我们需要使用vue.use(插件名) 来安装插件
 */
Vue.use(Router)
/*
 * 第二步: 构建VueRouter对象
 * 在VueRouter中主要是配置路由和组件之间的映射关系的.
 */
const routes = [
  {
    path:"/",
    redirect: "/home"
  }, {
    path: "/home",
    component: Home
  },{
    path: "/about",
    component: About
  },{
    path: "/user/:userId",
    component: User
  }
]

我们将代码的引入方式改变了,这样在打包的时候, 会将每一个import进来的文件打包成一个单独的js文件. 如下图所示:

59750c0b06b542acb5612f08a6f43271_tplv-k3u1fbpfcp-watermark.png

和之前相比, 多了3个文件, 因为使用了三个懒加载组件.

相关文章
|
6月前
|
JavaScript 前端开发
Vue3--Vue Router详解--学习笔记
Vue3--Vue Router详解--学习笔记
83 3
|
JavaScript CDN
【VUE】vue.js中的路由router
【VUE】vue.js中的路由router
|
6月前
|
JavaScript
vue.router和vue.route
vue.router和vue.route
|
3月前
|
资源调度 JavaScript 前端开发
Vue Router 的使用方式是什么
【8月更文挑战第30天】Vue Router 的使用方式是什么
20 2
|
4月前
|
JavaScript
vue $router与$route的区别详解
vue $router与$route的区别详解
30 0
|
6月前
|
JavaScript
|
缓存 JavaScript
Vue Router 学习 new Router
Vue Router 学习 new Router
145 0
|
6月前
|
缓存 移动开发 JavaScript
【学习笔记】Vue Router
【学习笔记】Vue Router
58 0
|
6月前
|
JavaScript 前端开发 网络架构
Vue Router:让你的应用路由起来!
Vue Router:让你的应用路由起来!
|
JavaScript
Vue(Vue2+Vue3)——70.<router-link>的replace属性
Vue(Vue2+Vue3)——70.<router-link>的replace属性
Vue(Vue2+Vue3)——70.<router-link>的replace属性