【前端 Vue】07 - Vue-router
1. 后端路由阶段
早期的网站开发整个
HTML
页面是由服务器来渲染的。服务器直接生产渲染好对应的HTML页面, 返回给客户端进行展示。
1.1 但是, 一个网站, 这么多页面服务器如何处理呢?
-
一个页面有自己对应的网址, 也就是
URL
。 -
URL
会发送到服务器, 服务器会通过正则对该URL
进行匹配, 并且最后交给一个Controller
进行处理。 -
Controller
进行各种处理, 最终生成HTML
或者数据, 返回给前端。 -
这就完成了一个
IO
操作。
上面的这种操作, 就是后端路由,当我们页面中需要请求不同的路径内容时, 交给服务器来进行处理, 服务器渲染好整个页面, 并且将页面返回给客户端,这种情况下渲染好的页面, 不需要单独加载任何的
js
和css
, 可以直接交给浏览器展示, 这样也有利于SEO
的优化。
1.2 后端路由的缺点:
-
一种情况是整个页面的模块由后端人员来编写和维护的;
-
另一种情况是前端开发人员如果要开发页面, 需要通过
PHP
和Java
等语言来编写页面代码; -
而且通常情况下HTML代码和数据以及对应的逻辑会混在一起, 编写和维护都是非常糟糕的事情。
2. 前端路由阶段
2.1 前后端分离阶段
-
随着
Ajax
的出现, 有了前后端分离的开发模式。 -
后端只提供
API
来返回数据, 前端通过Ajax
获取数据, 并且可以通过JavaScript
将数据渲染到页面中。 -
这样做最大的优点就是前后端责任的清晰, 后端专注于数据上, 前端专注于交互和可视化上。
-
并且当移动端
(iOS/Android)
出现后, 后端不需要进行任何处理, 依然使用之前的一套API
即可。
2.2 单页面富应用阶段
-
其实SPA最主要的特点就是在前后端分离的基础上加了一层前端路由。
-
也就是前端来维护一套路由规则。
3. URL的hash 模式 和 HTML5 的 history 模式
3.1 URL的hash模式
-
URL
的hash
也就是锚点(#
), 本质上是改变window.location
的href
属性;我们可以通过直接赋值location.hash
来改变href
, 但是页面不发生刷新。
3.2 HTML5的history模式
-
history
对象的pushState
方法传递三个参数,第一个参数是一个对象。第二个参数是title
, 第三个参数是路径。
-
history
模式的replaceState
方法:替换路径,不能通过返回箭头返回。
-
history
模式的go
方法:到某个索引的路径下:
history.go(-1) // 表示后退一步 和 history.back() 类似
history.go(1) // 表示前进一步 和 history.forward() 类似
4. Vue-Router的安装配置
- Vue-router是
Vue.js
官方的路由插件,它和
4.1 安装 Vue-Router
- 安装为一个运行时依赖:
npm install vue-router --save
-
创建一个
router
文件夹,并在文件中创建一个index.js
文件。 -
在
index.js
文件中引入VueRouter
对象和Vue
对象。
import VueRouter from 'vue-router';
import Vue from 'vue';
- 通过Vue.use(传入插件)安装该插件,任何Vue的插件都要使用 Vue.use进行安装。
Vue.use(VueRouter);
- 创建
VueRouter对象实例
,注意这里是 routes 而不是 routers 重要重要重要
// 路由数组
const routes = [];
// 2. 创建VueRouter对象
const router = new VueRouter({
// 配置组件之间的映射关系
// 对象属性的简写
routes
});
- 导出
VueRouter
对象实例:
export default router;
- 在
main.js
中引入并使用router
:
4.2 配置路由的映射关系
- 在
components
文件夹下创建Home
和About
组件。
- 在
router/index.js
下配置路由映射关系 。
- 使用
Vue
中注册的全局组件router-link
和router-view
实现页面跳转和渲染。
<div id="app">
<!-- router-link是Vue中注册的全局组件 -->
<router-link to="/home">首页</router-link>
<router-link to="/about">关于</router-link>
<router-view></router-view>
</div>
-
<router-link>
: 该标签是一个vue-router
中已经内置的组件, 它会被渲染成一个<a>
标签。 -
<router-view>
: 该标签会根据当前的路径, 动态渲染出不同的组件。 -
默认显示首页:
/home
,将进入页面时将页面重定向到Home
页面
// 路由数组
const routes = [
{
path: '/',
/* 将路径重定向到home */
redirect: '/home'
},
{
path: '/home',
name: 'Home',
component: Home
},
{
path: '/about',
component: About
}
]
4.3 修改路由的模式为 history
- 默认情况下,路径改变使用的是
URL
的hash
,如果希望使用HTML5
的history
模式可以进行如下的修改。
// 2. 创建VueRouter对象
const router = new VueRouter({
// 配置组件之间的映射关系
// 对象属性的简写 但是这个属性必须交 routes
routes,
mode:'history'
});
4.4 router-link 的其他属性
router-link
标签的 tag
属性
- 可以 通过
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
属性
-
replace
属性设置之之后通过该标签跳转的路径,不能通过浏览器的后退键返回。replace
不会留下history
记录, 所以指定replace
的情况下, 后退键返回不能返回到上一个页面中。这就说明vue-router
默认使用的是history
的pushState
。
<!-- 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
属性
- 默认情况下当点击某个标签,该标签被激活之后,在其中会添加一个
class
,router-link-active
。可以通过该class
设置激活样式。
.router-link-active {
color: #f00;
}
按钮被激活
- 该
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 通过代码实现路由的跳转
- 在页面中定义两个按钮实现路由的跳转:利用
vue
内置的$router
的push
和replace
方法实现跳转。
<!-- 通过代码实现路由的跳转 -->
<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 动态路由的使用
- 创建一个
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组件的路由
- 在
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
- 在跳转到
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文件夹下的JS7. 路由的懒加载
-
路由懒加载的官方解释:首先, 我们知道路由中通常会定义很多不同的页面,这个页面最后被打包在哪里呢? 一般情况下, 是放在一个
js
文件中,但是, 页面这么多放在一个js
文件中, 必然会造成这个页面非常的大,
如果我们一次性从服务器请求下来这个页面, 可能需要花费一定的时间, 甚至用户的电脑上还出现了短暂空白的情况。 -
路由懒加载做了什么? 答: 路由懒加载的主要作用就是将路由对应的组件打包成一个个的
js
代码块。只有在这个路由被访问到的时候, 才加载对应的组件。
7.2 各种路由懒加载的配置方式
- 方式一: 结合
Vue
的异步组件和Webpack
的代码分析
const Home = resolve => { require.ensure(['../components/Home.vue'], () => { resolve(require('../components/Home.vue')) })};
- 方式二:
AMD
写法
const About = resolve => require(['../components/About.vue'], resolve);
- 方式三: 在
ES6
中, 我们可以有更加简单的写法来组织Vue
异步组件和Webpack
的代码分割
const Home = () => import('../components/Home.vue')
8. 认识路由的嵌套
理解路由的嵌套8.1 嵌套路由配置案例
- 创建一个
HomeMessage
和HomeNews
组件。
<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>
- 配置嵌套路由 :
/* 使用懒加载的方式加载组件 */
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
}
];
嵌套路由的详细配置
- 因为这两个组件需要在
Home
组件中切换显示,所以还需在Home
组件中使用router-link
和router-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参数对象传递案例
- 创建一个新的组件
Profile
<template>
<div>
<h2>我是Profile组件</h2>
</div>
</template>
<script>
export default {
name: "profile"
}
</script>
<style scoped>
</style>
- 为组件配置路由 :
- 使用
router-link
的方式实现路由的跳转并传递query
参数对象。
- 使用触发事件的方式实现路由的跳转:通过
this.$router.push(``)
的方式实现路由跳转。
10. vue-router 和 vue-route 是由区别的
-
$router
为VueRouter
实例,想要导航到不同URL
,则使用$router.push
方法。 -
$route
为当前router
跳转对象里面可以获取name、path、query、params
等。
11. 导航守卫
1.有时可能需要在跳转过程之间做一些新的操作。就可以使用导航守卫监听跳转过程。
-
URL组成:
URL= scheme(协议)://host(主机):port(端口)/path(路径)?query(查询)#fragment(片段)
;
11.1 当页面跳转的时候如果需要改变 title 该如何做?
-
网页标题是通过
<title>
来显示的, 但是SPA
只有一个固定的HTML
, 切换不同的页面时, 标题并不会改变。 -
但是我们可以通过
JavaScript
来修改<title>
的内容window.document.title = '新的标题'
。
- 那么在
Vue
项目中, 在哪里修改? 什么时候修改比较合适呢?
使用导航守卫在路由跳转前进行修改页面 title
操作
-
使用
router
实例对象的beforeEach
方法前置守卫函数,函数中传递一个钩子函数,钩子函数需要 3 个参数。to , from ,next
。需要向下执行就需要调用next()
。 -
在执行
next()
之前将title
进行修改。但是动态的title
从哪里来呢?
11.2 导航守卫的分类
-
全局路由守卫;
-
路由独享守卫;
-
组件内守卫。
-
参考。
12. vue-router 的 keep-alive
-
keep-alive
是一个标签,是一个保持组件为活跃状态,不会被频繁的创建和频繁的销毁。
12.1 利用 keep-alive 和 activated 、beforeRouteLeave 导航守卫实现记住上一个页面的选择案例
keep-alive实现记住上一次 默认home路径- 当
router-view
标签外面包裹了keep-alive
标签之后activated
方法就会有效:在该方法中实现路由的跳转。
- 当离开当前的组件之前记录一下当前的路径
path
。
在beforeRouteLeave方法中就是离开组件之前记住上次的路径
只有使用 keep-alive标签包裹的组件使用 activated 和 deactived 才是有效的。
12.2 keep-alive的其他属性
keep-alive
是 Vue
内置的一个组件,可以使被包含的组件保留状态,或避免重新渲染。
-
include
: 字符串或正则表达,只有匹配的组件会被缓存; -
exclude
: 字符串或正则表达式,任何匹配的组件都不会被缓存;
<!-- 但是中间不要随便加空格 -->
<keep-alive exclude="profile,User">
<router-view></router-view>
</keep-alive>