路由懒加载
认识路由的懒加载
在使用懒加载之前,先对项目执行打包 `npm run build`,打包后生成3个js文件
在app.js文件中包含所有的业务代码,必然会造成内容非常大
如果一次性从服务器请求这个页面,可能需要花费一定时间,甚至用户的电脑还会出现短暂的空白情况,这时候就可以使用懒加载了
路由懒加载官方解释:
- 当打包构建应用时,JavaScript包会变得非常大,影响页面加载
- 如果我们能把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应组件,这样就更加高效了
路由懒加载做了什么?
- 路由懒加载的主要作用是将路由对应的组件打包成一个个的js代码块
- 只有在这个路由被访问时,才加载对应的组件
路由懒加载的效果
懒加载的方式
方式一:结合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')
路由嵌套
嵌套路由是一个很常见的功能
比如,在home页面中,希望通过/home/news和/home/message访问一下内容
一个路径映射一个组件,访问者两个路径也分别渲染两个组件
实现嵌套路由有两个步骤
- 创建对应的子组件,并在路由映射中配置对应的子路由
- 在组件内部使用<router-view>标签
传递参数
创建一个新的组件,并将其配置好
<!-- 创建新的组件Profile.vue -->
<template>
<div>
<h2>我是Profile组件</h2>
</div>
</template>
<script>
export default {
name: 'Profile'
}
</script>
<style scoped>
</style>
// index.js 配置路由映射
const Profile = () => import("../components/Profile");
const routes = [
...,
{
path: "/profile",
component: Profile
}
]
<!-- App.vue中添加跳转 -->
<router-link to="/profile" tag="button">档案</router-link>
传递参数的方式
有两种类型:params和query
params的类型
- 配置路由格式: /router/:id
- 传递的方式:在path后面跟上对应的值
- 传递后形成的路径:/router/abc
query的类型
- 配置路由格式:/router,也就是普通配置
- 传递的方式:对象中使用query的key作为传递方式
- 传递后行程的路径:/router?id=123&name=abc
传参方式一:<router-link>
传参方式二:JavaScript代码
获取参数
获取参数通过$route对象获取。在使用了vue-router的应用中,路由对象会被注入到每个组件中,赋值为 this.$route,并且当路由切换时,路由对象会被更新
$route和$router的区别
$router是VueRouter的实例,想要导航到不同的URL,使用$router.push方法
$route是当前router跳转对象中活动的组件对象,可以获取name、path、query、params等
导航守卫
为什么使用导航守卫?
考虑一个需求:在SPA应用中,如何改变网页的标题呢?
- 首先,网页的标题是通过index.html中<title>来显示的,在切换不同页面时,标题并不会改变
- 但可以通过JavaScript的方式来修改<title>的内容
普通的修改方式:
- 在每个路由对应的组件.vue文件中,使用生命周期函数,执行对应代码的修改
- 这种方法,在页面比较多的时候,不容易维护(需要再多个页面执行类似的代码)
// Home.vue
export default {
name: 'Home',
created() {
document.title = '首页'
},
}
// About.vue
export default {
name: 'About',
created() {
document.title = '关于'
},
}
...
什么是导航守卫?
- vue-router提供的导航守卫主要用来监听路由的进入和离开
- vue-router提供了beforeEach和afterEach的钩子函数,它们会在路由即将改变前和改变后触发
使用beforeEach完成标题的修改
- 首先,在映射关系中配置meta定义
- 其次,利用导航守卫,修改标题
// 前置守卫(guard)
// to: 即将要进入的目标的路由对象
// form: 当前导航即将要离开的路由对象
// next: 调用该方法后,才能进入下一个钩子
router.beforeEach((to, from, next) => {
// 从from跳转到to
document.title = to.matched[0].meta.title;
next();
});
导航守卫补充
一:如果是后置钩子,也就是afterEach,不需要主动调用next()函数
// 后置钩子(hook)
router.afterEach((to, from) => {});
二:上面使用的导航守卫, 被称之为全局守卫
路由独享的守卫
beforeEnter守卫只有进入路由时触发
const routes = [
{
path: "/user/:userId",
component: User,
meta: {
title: "用户"
},
beforeEnter: (to, from, next) => {
console.log("user");
next();
}
},
]
组件内的守卫
const UserDetails = {
template: `...`,
beforeRouteEnter(to, from) {
// 在渲染该组件的对应路由被验证前调用
// 不能获取组件实例 `this` !
// 因为当守卫执行时,组件实例还没被创建!
},
beforeRouteUpdate(to, from) {
// 在当前路由改变,但是该组件被复用时调用
// 举例来说,对于一个带有动态参数的路径 `/users/:id`,在 `/users/1` 和 `/users/2` 之间跳转的时候,
// 由于会渲染同样的 `UserDetails` 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
// 因为在这种情况发生的时候,组件已经挂载好了,导航守卫可以访问组件实例 `this`
},
beforeRouteLeave(to, from) {
// 在导航离开渲染该组件的对应路由时调用
// 与 `beforeRouteUpdate` 一样,它可以访问组件实例 `this`
},
}
更多内容,可查看官网 导航守卫 | Vue Router
keep-alive
keep-alive是Vue内置的一个组件,可以使被包含的组件保留状态,或避免重新渲染
- 它有两个非常重要的属性:
- include - 字符串或正则表达式,只有匹配的组件会被缓存
- exclude - 字符串或正则表达式,任何匹配的组件都不会被缓存
router-view也是一个组件,如果直接被包在keep-alive里面,所有路径匹配到的视图组件都会被缓存:
<keep-alive>
<router-view>
<!-- 所有路径匹配到的视图组件都会被缓存 -->
</router-view>
</keep-alive>
activated、deactivated这两个函数,只有该组件被保持了状态使用了keep-alive时,才是有效的
// Home.vue 验证activated、deactivated什么时候有效
export default {
name: 'Home',
...,
// 活跃的
activated() {
console.log('activated');
},
// 不活跃的
deactivated() {
console.log('deactivated');
}
}
需求:首页选中消息后,切换回来还是显示消息内容
未修改之前的效果,选中消息后,切换回来又重新选中了新闻,这是因为切换到首页时,拼接的路径是/home,根据映射配置重新指向了/news
解决方案:
- 取消首页的重定向配置,
- 在Home.vue中定义path属性,记录当前路径,默认为 '/home/news'
- 使用组件内导航守卫,记录路由离开之前的路径
- 使用activated函数,重新设置路径
// Home.vue
export default {
name: 'Home',
data () {
return {
// 定义默认路径
path: '/home/news'
}
},
activated() {
// 设置活跃时显示路径
this.$router.push(this.path)
},
// 离开之前记录当前路径
beforeRouteLeave (to, from, next) {
this.path = this.$route.path
next()
}
}
需求:用户和档案两个页面不使用缓存
解决方案:使用exclude属性
<!-- exclude="组件的name,多个使用逗号拼接,逗号后不能加空格" -->
<keep-alive exclude="User,Profile">
<router-view />
</keep-alive>
通过created+destroyed生命周期函数来验证
路由相关笔记:vue2.x笔记9-vue-router(1)_notChange的博客-CSDN博客本文包括认识路由(包含后端路由阶段、前后端分离阶段、单页面富应用阶段),前端路由的规则、vue-router基础以及细节处理https://blog.csdn.net/notChange/article/details/123128671?spm=1001.2014.3001.5501
vue2.x 路由TabBar练习_notChange的博客-CSDN博客结合路由实现TabBar组件的封装https://blog.csdn.net/notChange/article/details/123250086