1.什么是路由
1.认识路由
- 路由是通过互联的网络把信息从源地址传输到目的地址的活动
- 路由器提供了两种机制:路由和转送
路由是决定数据包从来源到目的地的路径
转送将输入端的数据转移到合适的输出端 - 路由表本质上是一个映射表,决定了数据包的指向
2.前端渲染和后端渲染(理解)
①后端渲染
- jsp:java server page
- 又称为服务器渲染
- html+css+java,java代码作用是从数据库中读取数据,并且将它动态的放在页面中
②前端渲染
- 浏览器中显示的网页中的大部分内容,都是由前端写的js代码在浏览器中执行,最终渲染出来的网页
3.前端路由和后端路由(理解)
①后端路由
- 后端路由:后端处理URL和页面之间的映射关系
- 后端路由阶段
②前端路由
- 前后端分离阶段
- 单页面富应用阶段
- 前端路由的核心:改变URL,但是页面不进行整体的刷新
- 前端路由实际上是url和组件的映射关系
2.url的hash和HTML5的history
- 如何改变URL,但是页面不进行整体的刷新:url的hash和html5的history
①URL的hash
- 通过直接赋值location.hash来改变href
②HTML5的history模式:pushState
- history.pushState(data,title,?url)
一般是history.pushState({},‘’,url) - 示例
- 有点类似于栈结构
- 可以通过history.back()回到上一个页面
③HTML5的history模式:replaceState
- history.replaceState({},‘’,url),注意url要打引号
- 这个方式无法使用回退按钮回退,不保留历史记录
④HTML5的history模式:go
- history.back()等价于history.go(-1)
- history.forward等价于history.go(1)
- go只能在pushState里使用,才能访问历史记录
3.安装和配置方式
1.认识vue-router
- 目前流行的三大框架,都有自己的路由实现
Angular的ngRouter
React的ReactRouter
Vue的vue-router - vue-router是基于路由和组件的
路由用于设定访问路径,将路径和组件映射起来
在vue-router的单页面应用中,页面的路径的改变就是组件的切换
2.安装vue-router
- 安装:
npm install vue-router --save
- 在模块化工程中使用它(因为是一个插件,所以可以通过Vue.use()来安装插件即路由功能)
①导入路由对象,调用Vue.use(VueRouter)
②创建路由实例,并且传入路由映射配置
③在Vue实例中挂载创建的路由实例 - 搭建路由框架
3.使用vue-router步骤
- 步骤:
①创建路由组件
②配置路由映射:组件和路径映射关系
③使用路由:通过<router-link>
和<router-view>
- 代码示例
index.js文件
About.vue和Home.vue文件
App.vue文件 <router-link>
该标签是一个vue-router中已经内置的组件,它会被渲染成一个<a>
标签<router-viewer>
该标签会根据当前的路径,动态渲染出不同的组件- 在路由切换时,切换的是
<router-viewer>
挂载的组件,其他内容不会发生改变
4.路由的默认值和修改为history模式
- 路由的默认路径:
- HTML5的history模式
默认情况下,是哈希hash模式,即在更改路径时会有“#”的出现
如何修改为history模式:
4.router-link
的其他属性补充
1.属性:to
用于指定跳转的路径,且把<router-link>
渲染成a标签
2.tag属性
tag可以指定<router-link>
之后渲染什么组件,比如<router-link to='/home' tag='button'>
3.replace属性
replace不会留下history记录,指定replace的情况下,后退键返回不能返回到上一个页面中<router-link to='/home' replace>
4.active-class属性
- 当
<router-link>
对应的路由匹配成功时,会自动给当前元素设置一个router-link-active的class值,设置active-class属性可以修改默认的名称 - 通常不会修改类的属性,会直接使用默认的
- 如果我们不希望大量标签都要写上active-class,则可以在路由配置index.js中,添加linkActiveClass属性
5.通过代码跳转路由
<template>
<div id="app">
<button @click="homeClick">首页</button>
<button @click="aboutClick">关于</button>
</div>
</template>
<script>
export default {
name: 'App',
methods: {
homeClick() {
//push相当于pushState
this.$router.push('/home')
// 还可以用replace的方法
this.$router.replace('/home')
},
aboutClick() {
this.$router.push('/about')
}
}
}
</script>
6.动态路由的使用
-
某些情况下,一个页面的path路径可能是不确定的,比如进入用户界面,我们希望除了前面的/user外,后面还跟上了用户的ID,如/user/slineee
-
这种path和component的匹配关系,称为动态路由,也是路由传递数据的一种方式
-
index.js里配置用户
App.vue中,通过v-bind绑定to属性
User.vue中 -
$router获取的是vueRouter路由对象
$route是获取当前处于活跃状态的路由
7.路由的懒加载
1.打包文件的解析
js里的第一个文件是当前应用程序开发的所有代码(业务代码)
第二个文件:为打包的代码作底层支撑
第三个文件:提供商,第三方vue,vue-router,axios
2.作用
- 当打包构建应用时,js包会变得非常大,影响页面加载(甚至导致有一个页面空白期);
所以我们希望能把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应组件,这样更加高效 - 路由懒加载的作用就是将路由对应的组件打包成一个个的js代码块,只有在这个路由被访问到的时候,才加载对应的组件
- 效果
3.懒加载的方式
- 三种方式:推荐方式三
- 示例
8.路由的嵌套使用
1.什么是嵌套路由
- 比如home页面中,我们希望通过/home/news和/home/message访问一些内容
- 一个路径映射一个组件,访问这两个路径也会分别渲染两个组件
2.实现嵌套路由
- 两个步骤:
创建对应的子组件,并在路由映射中配置对应的子路由
在组件内部使用<router-view>
标签 - 创建HomeNews和HomeMessage两个组件
- 并且引入:在Home的children里面添加,并且子路由不需要加’/’,因为是相对路径
<script>
const HomeNews = () => import('../components/HomeNews.vue')
const HomeMessage = () => import('../components/HomeMessage.vue')
export default new Router({
routes: [
{
path: '/home',
component: Home,
children: [
//默认路径
{
path: '',
redirect: 'news'
},
{
// 子路由时不需要加‘/’
path: 'news',
component: HomeNews
},
{
path: 'message',
component: HomeMessage
}
]
}
})
</script>
在Home组件的模板中添加标签,Home.vue如下:
注意这里的to要用绝对路径
9.参数传递
1.params
- 传递参数的类型由:params和query
- params的类型:
配置路由格式:/router/:id
传递的方式:在path后面跟上对应的值(router-link标签绑定to属性,并用字符串拼接)
传递后形成的路径:/router/aaa,/router/bbb - 在User.vue中通过
$route.params.id
取到对应的值
2.query:用于有大量的数据需要传递
- query的类型:
配置路由格式:/router,即普通配置
传递的方式:对象中使用query的key作为传递方式
传递后形成的路径:/router?id=123,/router?id=abc - 代码示例:则显示 http://localhost:8080/profile?name=why&age=18&height=185
//注意这里是用v-bind绑定属性
<router-link :to="{path: '/profile',query:{name:'why',age:18,height:185}}">档案</router-link>
- URL:协议://主机:端口/路径?查询(query)
scheme://host:port/path?query#fragment - 在profile.vue中通过
{{$route.query.name/age/height}}
取到对应的值
3.通过代码实现
<template>
<div id="app">
<button @click="userClick">首页</button>
<button @click="profileClick">关于</button>
</div>
</template>
<script>
export default {
name: 'App',
data() {
return{
userID = 'slineee'
}
}
methods: {
userClick() {
//push相当于pushState
this.$router.push('/user'+this.userID)
},
profileClick() {
this.$router.push({
path: '/profile',
query: {
name: 'slineee',
age: 18,
height:168
}
})
}
}
}
</script>
10.$route
和$router
的区别
$router
为VueRouter实例,想要导航到不同URL,则使用$router.push
方法$route
为当前router跳转对象里面可以获取name、path、query、params等
11.导航守卫
1.全局导航守卫
- 我们想要对组件来换跳转进行监听,我们可以采用生命周期函数
created(当组件被创建时执行回调函数)
mouted(当组件被挂载时执行回调函数)
updated(当组件数据更新执行回调函数) - 需求:点击每个组件,document.title会对应改变
- 法一:生命周期函数,但很麻烦,每个组件都要写;当页面比较多时,不容易维护
4. 如果我们想要监听路由跳转,可以用全局导航守卫首先要给每个组件定义mata
利用导航守卫
to:即将要进入的目标的路由对象
from:当前导航即将要离开的路由对象
next:调用该方法后,才能进入下一个钩子
<script>
//前置钩子:在跳转之前进行回调
router.beforeEach((to, from, next) => {
//document.title = to.meta.title;
document.title = to.matched[0].meta.title
// 一定要调用next(),否则router路由器中的所有组件都无法跳转
next()
//若不希望直接跳转比如登录注册
//可以加一些条件判断,跳转到对应的路径
//如if(){next('/login')}
})
</script>
- 遇到的问题:如果用脚手架默认生成的index.js文件,则会报错,原因是export default new Router({})导致没有router这个对象 ,而这个函数只能通过router调用
解决方法:export default new Router({})改为const router = new Router({}} 在其后加上export default router - 注意细节:当进去第一个得到的首页(home)标题是undefined,这是由于路由的嵌套造成的
通过打印to,有一个matched数组,matched[0]的path是’/home’,matched[1]的path是’/home/news’,永远取第一个
所以更改为document.title = to.matched[0].meta.title
2.后置钩子
- 跳转之后进行回调
- afterEach不需要主动调用next()函数
- 代码
<script>
router.afterEach((to, from) => {
})
</script>
- 以上我们使用的导航守卫被称为全局守卫
3.路由独享的守卫
- 只有进到某个路由里,才会回调函数
<script>
const routes = [
{
path:'/home',
component:Home,
meta:{
title:'主页'
},
beforeEnter:(to,from,next)=>{
console.log('slineeee');
next()
}
}
]
</script>
4.组件内的守卫
- 写在组件内
- 看官网学习
12.keep-alive
- 当我们切换组件时,组件内部的所有状态是没有被保留下来的,每次切换组件都会重新创建
- keep-alive是Vue内置的一个组件,可以使被包含的组件保留状态,或避免重新渲染
- 如何使用:
- 需求:进入首页默认是显示新闻,点击首页消息,再点击用户,当回到首页的时候,我们希望看到的是首页消息
- home.vue文件:
<script>
export default {
name:"Home",
data(){
return{
path:'/home/news'
}
},
activated () {
this.$router.push(this.path)
},
//导航离开该组件的对应路由时调用
//使用path属性记录离开时的路径
beforeRouteLeave(to,from,next){
//console.log(this.$route.path);
this.path = this.$route.path
next();
}
}
</script>
- activated()函数和deactivated()函数只有该组件被保持了状态,即使用了keep-alive时才是有效的
- 有时候我们并不希望所有组件都被缓存,有些组件我们希望每一次点击都重新创建,keep-alive有两个重要的属性
include:字符串或正则表达,只有匹配的组件会被缓存
exclude:字符串或正则表达式,任何匹配的组件都不会被缓存
用法:字符串是每个组件导出时候的name属性,且逗号后面不要随便加空格
13.文件路径引用问题
- 当我们复制代码到另一个文件时,很可能引起路径改变的问题,这时候我们可以给文件夹起个别名,找到对应文件夹下的文件
- 跟路径相关的配置在build/webpack.base.onf.js里修改
- 还可以在alias定义:
'assets':resolve('src/assets')//表示src下的assets文件夹
- 如果不是import里使用路径,而是在html里使用这种写法,则需要在前面加个波浪号~
- 注意改了config要重启服务