伴随着前端各种框架的出现,SPA(single page web application)应用势不可挡,伴随着的就是前端路由了
SPA最主要的特点就是在前后端分离的基础上加了一层前端路由
前端路由的核心
改变URL, 但是页面不进行整体的刷新。那问题就来了,我该怎么做?
- URL的hash
URL的hash也就是锚点(#),本质上是改变window.location的href属性。
我们可以通过直接赋值location.hash来改变href,但是页面不发生刷新
-
HTML5的history模式:pushState
history接口是HTML5新增的, 他有5种模式改变URL而不刷新页面
-
history.pushState()
-
history.replaceState()
-
history.back() | history.forward() | history.go()
- history.back() 等价于 history.go(-1)
- history.forward() 等价于 history.go(1)
在讲解vue中使用vue-router改变URL不刷新页面之前,先看一下
-
vue-router的使用
- 安装vue-router
npm install vue-router --save
- 在模块化工程中使用它(因为是一个插件,所以通过Vue.use()来挂载插件并使用)
- 导入路由对象,并且调用Vue.use(VueRouter)
- 创建路由实例,并且传入路由映射配置
- 在Vue实例中挂载创建的路由实例
- 使用vue-router的步骤
- 创建路由组件
- 配置路由映射:组件和路径映射关系
- 使用路由:通过 <router-link>和<router-view>
<router-link>
该标签是一个vue-router中已经内置的组件,他会被渲染成一个<a>
标签<router-view>
该标签会根据当前的路径,动态渲染出不同的组件- 在路由切换时,切换的是
<router-view>
挂载的组件,其他内容不会发生改变
- 路由的默认路径
默认情况下,进入网站的首页,我们希望<router-view>
渲染首页的内容。但是我们的实现中,默认没有显示首页组件,必须让用户点击才可以
- 我们只需要多配置一个路由映射关系就可以了
![12](/Volumes/Macintosh HD - 数据/Users/liubi_chaos_g/Pictures/12.png)
- path配置的是根路径
/
- redirect是重定向,也就是我们将根据路径重定向到
/home
的路径下
- HTML5的history模式
- 前面说过改变路径的方式有两种
- URL的hash
- HTML5的history
- 默认情况下,路径的改变使用的URL的hash
- 如果希望使用HTML5的history模式,配置如下:
router-link补充
前面的<router-link>
中,我们只是使用了一个属性to
,用于指定跳转的路径
<router-link>
还有一些其他属性:
- tag:tag可以指定
<router-link>
之后渲染成什么组件,比如<router-link to='/home' tag='li'>
会渲染成一个<li>
元素,而不是<a>
- replace:replace不是留下history记录,所以指定replace的情况下,后退键返回到上一个页面中
- active-class:当
<router-link>
对应的路由匹配成功时,会自动给当前元素设置一个router-link-active的class,设置active-class可以修改默认的名称-
在进行高亮显示的导航菜单或者底部tabbar时,会使用该类
-
但是通常不会修改类的属性,会直接使用默认的router-link-active即可
-
修改linkActiveClass,可以通过router实例的属性进行修改
-
路由代码跳转
有时候,页面的跳转可能需要执行对应的JavaScript代码,这个时候,就可以使用第二种跳转方式了
代码修改如下图
动态路由
在某些情况下,一个页面的path路径可能是不确定的,比如我们进入用户界面时,希望是这样的路径/user/aaa或、user/mmm
这种path和Component的匹配关系,我们称之为动态路由(也是路由传递数据的一种方式)
- 路由代码
{
path: '/user/:id',
component: User
}
- 组件代码
<template>
<div>
<h2>我是用户页面</h2>
<p>用户页面有下面这些信息,通过params传过来的</p>
<h4>{{$route.params.id}}</h4>
</div>
</template>
- 父组件代码
<router-link :to="'/user/' + id">用户</router-link>
或者
<router-link to="/user/zhangsan">用户</router-link>
-
效果图
路由的懒加载
- 路由的懒加载的主要作用就是将路由对应的组件打包成一个个的js代码块
- 只有在这个路由被访问到的时候,才加载对应的组件
如图:没有使用懒加载,最终编译的文件只有四个(使用vue4.0)
如图:使用了路由懒加载,每个路由文件都会单独编译成一个文件
-
懒加载的方式
- 方式一:结合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')
嵌套路由
注意点:
- 配置嵌套路由的映射关系时,path不需要添加
/
- 路由跳转时,需要填写完整的路由映射;如home下面有个news嵌套路由,代码
<router-link to="/home/news"></router-link>
// 路由配置
{
path: '/home',
component: Home,
children: [
{
path: '',
redirect: 'message'
},
{
path: 'message',
component: Message
},
{
path: 'news',
component: News
}
]
}
<template>
<div>
<h2>我是首页</h2>
<p>我是首页的内容</p>
<router-link to="/home/message">未读消息</router-link>
<router-link to="/home/news">整点新闻</router-link>
<router-view></router-view>
</div>
</template>
传递参数的方式
-
传递参数主要有两种类型:params和query
-
params的类型
- 配置路由格式:
/router/:id
- 传递的方式:在path后面跟上对应的值
- 传递后形成的路径:
/router/123ab
- 配置路由格式:
-
query的类型
- 配置路由格式:
/router
,也就是普通配置 - 传递的方式:对象中使用query的key作为传递方式
- 传递后形成的路径:
/router?id=123&age=23
- 配置路由格式:
-
方式一:
<router-link>
<router-link :to="{ path: '/profile', query: { name: 'chaos', age: 11, hobby: 'music' } }">档案</router-link>
- 方式二:js代码
toProfile() {
this.$router.push({
path: '/profile',
query: {
name: 'chaos',
age: 11,
hobby: 'girl'
}
})
}
- 获取参数
<template>
<div>
<h2>我是档案页面,我会将传递过来的参数展示到下面</h2>
<p>这是通过params传递过来的参数{{$route.params}}</p>
<p>这是通过query传递过来的参数{{$route.query}}</p>
</div>
</template>
$router和$route的区别
- $router是VueRouter的实例,想要导航到不同的URL,则使用$router -- 路由的调度者
- $route为当前router跳转对象,路由本身;可以获取name、path、query、params等
导航守卫
-
vue-router提供的导航守卫主要用来监听路由的进入和离开的
-
vue-router提供了beforeEach和afterEach的钩子函数,他们会在路由即将改变前和改变后触发
-
我们可以利用beforeEach来完成标题的修改
- 首先,我们可以在路由映射中定义一些标题,可以利用meta来定义
- 其次,利用导航守卫,修改标题
{ path: '/home', component: Home, meta: { title: '首页' }, children: [ { path: '', redirect: 'message' }, { path: 'message', component: Message }, { path: 'news', component: News } ] }, { path: '/about', component: About, meta: { title: '关于' } },
router.beforeEach((to, from, next) => { console.log(to) document.title = to.matched[0].meta.title next() })
-
导航钩子的三个参数解析
- to:即将要进入的目标的路由对象
- from:当前导航即将要离开的路由对象
- next:调用该方法后,才能进入下一个钩子
keep-alive
- keep-alive是vue内置的一个组件,可以使被包含的组件保留状态,或避免重新渲染。有两个非常重要的属性(属性里面不要随便加空格,造成匹配错误)
- include - 字符串或正则表达式,只有匹配的组件才会被缓存
- exclude - 字符串或正则表达式,任何匹配的组件都不会被缓存
- router-view也是一个组件,如果直接被包在keep-alive里面,所有路径匹配到的试图组件都会被缓存