【前端 Vue】07 - Vue-router

1. 后端路由阶段

早期的网站开发整个HTML页面是由服务器来渲染的。服务器直接生产渲染好对应的HTML页面, 返回给客户端进行展示。

1.1 但是, 一个网站, 这么多页面服务器如何处理呢?

  1. 一个页面有自己对应的网址, 也就是URL

  2. URL会发送到服务器, 服务器会通过正则对该URL进行匹配, 并且最后交给一个Controller进行处理。

  3. Controller进行各种处理, 最终生成HTML或者数据, 返回给前端。

  4. 这就完成了一个IO操作。

上面的这种操作, 就是后端路由,当我们页面中需要请求不同的路径内容时, 交给服务器来进行处理, 服务器渲染好整个页面, 并且将页面返回给客户端,这种情况下渲染好的页面, 不需要单独加载任何的jscss, 可以直接交给浏览器展示, 这样也有利于SEO的优化。

1.2 后端路由的缺点:

  1. 一种情况是整个页面的模块由后端人员来编写和维护的;

  2. 另一种情况是前端开发人员如果要开发页面, 需要通过PHPJava等语言来编写页面代码;

  3. 而且通常情况下HTML代码和数据以及对应的逻辑会混在一起, 编写和维护都是非常糟糕的事情。

2. 前端路由阶段

2.1 前后端分离阶段

  1. 随着Ajax的出现, 有了前后端分离的开发模式。

  2. 后端只提供API来返回数据, 前端通过Ajax获取数据, 并且可以通过JavaScript将数据渲染到页面中。

  3. 这样做最大的优点就是前后端责任的清晰, 后端专注于数据上, 前端专注于交互和可视化上。

  4. 并且当移动端(iOS/Android)出现后, 后端不需要进行任何处理, 依然使用之前的一套API即可。

2.2 单页面富应用阶段

  1. 其实SPA最主要的特点就是在前后端分离的基础上加了一层前端路由。

  2. 也就是前端来维护一套路由规则。

3. URL的hash 模式 和 HTML5 的 history 模式

3.1 URL的hash模式

  1. URLhash也就是锚点(#), 本质上是改变window.locationhref属性;我们可以通过直接赋值location.hash来改变href, 但是页面不发生刷新。
location.hash改变location的href属性
地址栏是这样的

3.2 HTML5的history模式

  1. history对象的pushState方法传递三个参数,第一个参数是一个对象。第二个参数是title , 第三个参数是路径。
pushState方法
地址栏是这样的
  1. history模式的replaceState方法:替换路径,不能通过返回箭头返回。
history的replaceState方法
  1. history模式的go方法:到某个索引的路径下:
history.go(-1) // 表示后退一步  和 history.back() 类似 

history.go(1) // 表示前进一步 和 history.forward() 类似

4. Vue-Router的安装配置

  1. Vue-router是 Vue.js官方的路由插件,它和

4.1 安装 Vue-Router

  1. 安装为一个运行时依赖:
npm install vue-router --save 
  1. 创建一个router文件夹,并在文件中创建一个index.js文件。

  2. index.js文件中引入 VueRouter对象和 Vue对象。

import VueRouter from 'vue-router';
import Vue from 'vue';
  1. 通过Vue.use(传入插件)安装该插件,任何Vue的插件都要使用 Vue.use进行安装。
Vue.use(VueRouter);
  1. 创建 VueRouter对象实例注意这里是 routes 而不是 routers 重要重要重要
// 路由数组
const routes = [];

// 2. 创建VueRouter对象
const router = new VueRouter({
  // 配置组件之间的映射关系
  // 对象属性的简写
  routes
});
  1. 导出 VueRouter对象实例:
export default router;
  1. main.js中引入并使用 router
在`main.js`中引入并使用 `router`

4.2 配置路由的映射关系

  1. components文件夹下创建 HomeAbout组件。
  1. router/index.js下配置路由映射关系 。
配置路由映射关系
  1. 使用 Vue 中注册的全局组件 router-linkrouter-view实现页面跳转和渲染。
 <div id="app">
    <!-- router-link是Vue中注册的全局组件 -->
    <router-link to="/home">首页</router-link>
    <router-link to="/about">关于</router-link>
    <router-view></router-view>
  </div>
  1. <router-link>: 该标签是一个vue-router中已经内置的组件, 它会被渲染成一个<a>标签。

  2. <router-view>: 该标签会根据当前的路径, 动态渲染出不同的组件。

  3. 默认显示首页:/home,将进入页面时将页面重定向到 Home页面

// 路由数组
const routes = [
  {
    path: '/',
    /* 将路径重定向到home */
    redirect: '/home'
  },
  {
    path: '/home',
    name: 'Home',
    component: Home
  },
  {
    path: '/about',
    component: About
  }
]

4.3 修改路由的模式为 history

  1. 默认情况下,路径改变使用的是URLhash,如果希望使用 HTML5history模式可以进行如下的修改。
修改路由的模式为history
// 2. 创建VueRouter对象
const router = new VueRouter({
  // 配置组件之间的映射关系
  // 对象属性的简写 但是这个属性必须交 routes
  routes,
  mode:'history'
});

4.4 router-link 的其他属性

router-link 标签的 tag 属性
  1. 可以 通过 tag设置router-link使用什么标签来进行渲染。
<!-- router-link是Vue中注册的全局组件 -->
    <router-link tag="button" to="/home">首页</router-link>
    <router-link tag="button" to="/about">关于</router-link>
使用button标签进行渲染
router-link 标签的 replace 属性
  1. replace属性设置之之后通过该标签跳转的路径,不能通过浏览器的后退键返回。replace不会留下history记录, 所以指定replace的情况下, 后退键返回不能返回到上一个页面中。这就说明vue-router默认使用的是 historypushState
<!-- router-link是Vue中注册的全局组件 -->
    <router-link tag="button" to="/home" replace>首页</router-link>
    <router-link tag="button" to="/about" replace>关于</router-link>
不能通过浏览器的后退键返回
router-link 标签的 active-class 属性
  1. 默认情况下当点击某个标签,该标签被激活之后,在其中会添加一个classrouter-link-active。可以通过该class设置激活样式。
 .router-link-active {
    color: #f00;
  }
按钮被激活
  1. class的名称是可以被修改的,此时就需要在标签中 使用active-class属性对class的名称进行修改。
    <!-- router-link是Vue中注册的全局组件 -->
    <router-link tag="button" to="/home" replace active-class="active">首页</router-link>
    <router-link tag="button" to="/about" replace active-class="active">关于</router-link>
.active {
    color: #00f;
  }
使用active-class修改class的名称
router/index.js文件的router对象中使用linkActiveClass属性统一修改样式名称
统一对link激活样式名称进行修改
统一修改了link的样式名称
将link的激活样式名称修改为linkActive

4.5 通过代码实现路由的跳转

  1. 在页面中定义两个按钮实现路由的跳转:利用 vue内置的 $routerpushreplace方法实现跳转。
    <!-- 通过代码实现路由的跳转  -->
    <button @click="btnClickHome">首页</button>
    <button @click="btnClickAbout">关于</button>
      /**
       * 跳转到 首页
       */
      btnClickHome() {
        // this.$router.push('/home');
        this.$router.replace('/home'); // 跳转之后不能通过浏览器的后退按钮返回
      },

      /**
       * 实现跳转到关于
       */
      btnClickAbout() {
        // this.$router.push('/about');
        this.$router.replace('/about'); // 跳转之后不能通过浏览器的后退按钮返回
      }

5. vue-router 动态路由的使用

  1. 创建一个 User组件并在 router/index.js中配置路由:

// 路由数组
const routes = [
  {
    path: '/',
    /* 将路径重定向到home */
    redirect: '/home'
  },
  {
    path: '/home',
    name: 'Home',
    component: Home
  },
  {
    path: '/about',
    component: About
  },
  {
    path: '/user/:userId',
    component: User
  }
];
配置User组件的路由
  1. APP.vue中使用 router-link配置路由实现跳转:在配置时一并传递参数。
     <!-- 实现动态路由 -->
    <router-link to="/home">首页</router-link>
    <router-link to="/about">关于</router-link>
    <!-- 在此使用动态路由 使用 v-bind 动态绑定 -->
    <router-link :to="`/user/` + userId">用户</router-link>
使用v-bind动态绑定userId
  1. 在跳转到User组件之后,在User页面获取到路径中的userId参数:这里需要通过一个$route的属性获取。使用 $route.params.userId获取。但是这里的userId是与路由配置中的userId一一对应的。
 <div>
    <h2>我是User组件</h2>
    <!-- 获取到路径中传递的用户名 的两种方式-->
    <!-- 1. 直接在Mustache语法中写 -->
    <h2>{{$route.params.userId}} 您好!</h2>
    <!-- 2. 通过计算属性的方式 -->
    <h2>{{userId}} 您好!</h2>
  </div>
computed: {
      userId() {
        return this.$route.params.userId
      }
    }
通过$route.params.userId获取路径中userId参数

6. vue-router 打包文件的解析

打包之后的dist文件夹下的JS

7. 路由的懒加载

  1. 路由懒加载的官方解释:首先, 我们知道路由中通常会定义很多不同的页面,这个页面最后被打包在哪里呢? 一般情况下, 是放在一个js文件中,但是, 页面这么多放在一个js文件中, 必然会造成这个页面非常的大,
    如果我们一次性从服务器请求下来这个页面, 可能需要花费一定的时间, 甚至用户的电脑上还出现了短暂空白的情况。

  2. 路由懒加载做了什么? 答: 路由懒加载的主要作用就是将路由对应的组件打包成一个个的js代码块。只有在这个路由被访问到的时候, 才加载对应的组件。

配置路由懒加载前后

7.2 各种路由懒加载的配置方式

  1. 方式一: 结合Vue的异步组件和Webpack的代码分析
const Home = resolve => { require.ensure(['../components/Home.vue'], () => { resolve(require('../components/Home.vue')) })};
  1. 方式二:AMD写法
const About = resolve => require(['../components/About.vue'], resolve);
  1. 方式三: 在ES6中, 我们可以有更加简单的写法来组织Vue异步组件和Webpack的代码分割
const Home = () => import('../components/Home.vue')

8. 认识路由的嵌套

理解路由的嵌套

8.1 嵌套路由配置案例

  1. 创建一个 HomeMessageHomeNews组件。
<template>
  <div>
    <ul>
      <li>消息1</li>
      <li>消息2</li>
      <li>消息3</li>
      <li>消息4</li>
    </ul>
  </div>
</template>

<script>
    export default {
        name: "home-message"
    }
</script>

<style scoped>

</style>
<template>
  <div>
    <ul>
      <li>新闻1</li>
      <li>新闻2</li>
      <li>新闻3</li>
      <li>新闻4</li>
    </ul>
  </div>
</template>

<script>
    export default {
        name: "home-news"
    }
</script>

<style scoped>
</style>
  1. 配置嵌套路由 :
/* 使用懒加载的方式加载组件 */
const Home = () => import('../components/Home')
const HomeNews = () => import('../components/HomeNews')
const HomeMessage = () => import('../components/HomeMessage')
const About = () => import('../components/About')
const User = () => import('../components/User')

// 1. 通过Vue.use(传入插件)安装该插件,任何Vue的插件都要使用 Vue.use进行安装
Vue.use(VueRouter);

// 路由数组
const routes = [
  {
    path: '/',
    /* 将路径重定向到home */
    redirect: '/home'
  },
  {
    path: '/home',
    name: 'Home',
    component: Home,
    /* 配置路由的嵌套 */
    children:[
      /* 配置默认显示首页的时候一并显示消息 */
      {
        path:'/',
        redirect:'news'
      }
      ,
      {
        /* 注意这里没有 斜杠 / 这里是不能有 斜杠的  */
        path:'news',
        component:HomeNews
      },
      {
        path:'message',
        component:HomeMessage
      }
    ]
  },
  {
    path: '/about',
    component: About
  },
  {
    path: '/user/:userId',
    component: User
  }
];
嵌套路由的详细配置
  1. 因为这两个组件需要在 Home组件中切换显示,所以还需在Home组件中使用router-linkrouter-view进行配置。
<template>
  <div>
    <h2>我是Home组件</h2>
    <router-link to="/home/news">新闻</router-link>
    <router-link to="/home/message">消息</router-link>
    <router-view></router-view>
  </div>
</template>
在Home组件中使用 router-link 和 router-view进行配置

9. vue-router 参数传递

9.1 参数传递的方式一 user/:userId

使用在路由中配置的方式传递参数

9.2 参数传递的方式二 query参数对象传递案例

  1. 创建一个新的组件 Profile
<template>
  <div>
    <h2>我是Profile组件</h2>
  </div>
</template>

<script>
  export default {
    name: "profile"
  }
</script>

<style scoped>

</style>
  1. 为组件配置路由 :
为Profile组件配置路由
  1. 使用 router-link的方式实现路由的跳转并传递query参数对象。
使用 `router-link`的方式实现路由的跳转并传递`query`参数对象
  1. 使用触发事件的方式实现路由的跳转:通过this.$router.push(``)的方式实现路由跳转。
使用触发事件的方式实现路由的跳转

10. vue-router 和 vue-route 是由区别的

  1. $routerVueRouter实例,想要导航到不同URL,则使用$router.push方法。

  2. $route为当前router跳转对象里面可以获取name、path、query、params等。

vue-router和 vue-route是由区别的

11. 导航守卫

1.有时可能需要在跳转过程之间做一些新的操作。就可以使用导航守卫监听跳转过程。

  1. URL组成: URL= scheme(协议)://host(主机):port(端口)/path(路径)?query(查询)#fragment(片段)

11.1 当页面跳转的时候如果需要改变 title 该如何做?

  1. 网页标题是通过<title>来显示的, 但是SPA只有一个固定的HTML, 切换不同的页面时, 标题并不会改变。

  2. 但是我们可以通过JavaScript来修改<title>的内容 window.document.title = '新的标题'

  1. 那么在Vue 项目中, 在哪里修改? 什么时候修改比较合适呢?
使用导航守卫在路由跳转前进行修改页面 title操作
  1. 使用 router实例对象的beforeEach 方法前置守卫函数,函数中传递一个钩子函数,钩子函数需要 3 个参数。to , from ,next。需要向下执行就需要调用 next()

  2. 在执行next()之前将 title进行修改。但是动态的 title从哪里来呢?

在每一个route中定义一个meta元数据存放title

11.2 导航守卫的分类

  1. 全局路由守卫;

  2. 路由独享守卫;

  3. 组件内守卫。

  4. 参考

12. vue-router 的 keep-alive

  1. keep-alive 是一个标签,是一个保持组件为活跃状态,不会被频繁的创建和频繁的销毁。
保持组件为活跃状态不会被频繁的创建和销毁

12.1 利用 keep-alive 和 activated 、beforeRouteLeave 导航守卫实现记住上一个页面的选择案例

keep-alive实现记住上一次
默认home路径
  1. router-view标签外面包裹了keep-alive标签之后 activated方法就会有效:在该方法中实现路由的跳转。
在`router-view`标签外面包裹了`keep-alive`标签
  1. 当离开当前的组件之前记录一下当前的路径path
    在beforeRouteLeave方法中就是离开组件之前记住上次的路径
只有使用 keep-alive标签包裹的组件使用 activated 和 deactived 才是有效的。

12.2 keep-alive的其他属性

keep-aliveVue 内置的一个组件,可以使被包含的组件保留状态,或避免重新渲染。
  1. include : 字符串或正则表达,只有匹配的组件会被缓存;

  2. exclude : 字符串或正则表达式,任何匹配的组件都不会被缓存;

    <!-- 但是中间不要随便加空格 -->
    <keep-alive exclude="profile,User">
      <router-view></router-view>
    </keep-alive>

推荐阅读更多精彩内容