1、 路由懒加载
1.非懒加载
import List from '@/components/list.vue'
const router = new VueRouter({
routes: [
{ path: '/list', component: List }
]
})
2.箭头函数+import【懒加载】
const List = () => import('@/components/list.vue')
const router = new VueRouter({
routes: [
{ path: '/list', component: List }
]
})
3.箭头函数+require【懒加载】
const router = new Router({
routes: [
{
path: '/list',
component: resolve => require(['@/components/list'], resolve)
}
]
})
4.webpack
// r就是resolve
const List = r => require.ensure([], () => r(require('@/components/list')), 'list');
// 路由也是正常的写法 这种是官方推荐的写的 按模块划分懒加载
const router = new Router({
routes: [
{
path: '/list',
component: List,
name: 'list'
}
]
}))
6.为什么需要路由懒加载
如果没有配置懒加载,打包后的组件都在同一个文件bundle.js中,这样不管访问哪个界面,都要下载bundle.js 文件,这是资源的浪费,也会造成前端页面响应速度慢的问题
7.懒加载的优点
(1)将路由对应的组件打包成一个个js文件
(2)只有路由被访问时,才会加载对应的组件
8.实例
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')
5个懒加载组件,对应打包后的5个js文件
其中:app.xxx代表自己写的代码;ventor代码引入的第三方文件;manifest代表支持的底层代码;
2、hash和history的区别
hash模式
1.简介
hash是开发的传统模式,他的url中带着#,如上所示hash值就是#title
2.特点
hash值会出现在url中,但是不会出现在http请求中,对后端完全没有影响,所以改变hash值,不会向后端发请求,只会对前端自己的路由生效
3.原理
// hash模式的原始就是onhashchange事件
window.onhashchange = function(event){
console.log(event.oldURL, event.newURL);
}
onhashchange事件的好处就是hash值变化时,不会向后端发送请求,window就能监听事件的变化,然后加载响应的代码,除此之外,hash值的变化会被浏览器记录下来,所以就可以实现前进和后退操作,使用hash模式把页面的hash值和对应的url关联起来了
history模式
1.简介
history的url中没有#,它使用的是传统的路由分发模式,即一个用户输入url时,服务器就会接受这个请求,做出相应的逻辑处理
2.特点
history需要后台配置支持,如果后台没有对应的访问地址,就出报404
3.原理
history模式利用了html5提供的2个新的API pushState()和replaceState()修改浏览器的历史状态 利用forward()、back()、go()三个方法完成切换历史状态
4.API
pushState()、replaceState()、forward()、back()、go()
对比
1.获取2个值
hash——即地址栏URL中的#符号。比如在 http://localhost:8080/#/donate 中,hash的值就是#/donate,我们在浏览器中可以通过BOM中的变量获取到
history——history模式即是通过在host之后,直接添加斜线和路径来请求后端的一种URL模式。我们把demo中的vue-router调整到了history模式,获取window.location如下图:
2.是否向后台传参
在hash模式中,我们刷新一下上面的网页,可以看到请求的URL为http://localhost:8080/, 没有带上#/donate,说明在hash模式下,#后面的内容是不会包含在请求中的,只是会被前端浏览器利用
在history模式中,刷新一下网页,明显可以看到请求url为完整的url,url完整地请求了后端
3.是否刷新界面
调整到hash模式,在页面中通过 window.location.hash = '#/trans' 做了一个hash的跳转,我们可以看到浏览器的Network中没有进行新的请求,也就是说修改了hash参数,前端浏览器不会重新请求后端,只是会对前端自己的路由生效。
在history模式中,页面中通过 window.location.pathname = '/trans' 做一个路由跳转。可以看到,在对pathname重新赋值后,页面产生了新的请求trans。说明在history模式下,通过修改pathname直接修改路由,浏览器是会重新产生一个新的请求的。
3、如何获取页面的hash值
1.watch监听
// 监听,当路由发生变化的时候执行
watch: {
$route: {
handler: function(val, oldVal){
console.log(val);
},
// 深度观察监听
deep: true
}
},
2.window.location.hash
window.location.hash 的值可读可写,读取来判断状态是否改变,写入时可以在不重载网页的前提下,添加一条历史访问记录。
4、$route 和$router 的区别
$route 是“路由信息对象”,包括 path,params,hash,query,fullPath,matched,name 等路由信息参数
$router 是“路由实例”对象包括了路由的跳转方法,钩子函数等。
💡思考
push、replace区别
可以把路由router想象成一个访问记录栈,push是向栈中加入一个新记录,replace是替换掉栈顶 一般情况下要前进后退的浏览器管理,基本选择push,一些特殊的情况需要用到replace 比如,有一个授权页,用户在按流程操作时,某一步需要授权,是直接跳到授权页,授权页提交授权请求,直到成功授权后,跳到流程中的下一步操作的地址。此处,授权请求的那页面应该用replace去替换掉自身的访问记录,防止用户跳到下一步流程后按后退键回退到授权页,而导致重复授权。
5、路由动态传参的方式
params 方式
1.路由定义
//在index.js
{
path: '/user/:uname',
component: User,
},
2.跳转方式
// 方法1:
<router-link :to="{ name: 'users', params: { uname: wade }}">按钮</router-link
// 方法2:
this.$router.push({name:'users',params:{uname:wade}})
// 方法3:
this.$router.push('/user/' + wade)
3.获取参数
this.$route.params.uname
4.特点
但是params有一个特点就是刷新界面,参数会丢失,如果不想丢失就要在path后面加上参数,那就会url中显示参数,和query没有区别
query方式
1.路由定义
{
path: '/user',
name: 'user',
component: user
}
2.路由跳转
// 方法1:
<router-link :to="{ name: 'users', query: { uname: james }}">按钮</router-link>
// 方法2:
this.$router.push({ name: 'users', query:{ uname:james }})
// 方法3:
<router-link :to="{ path: '/user', query: { uname:james }}">按钮</router-link>
// 方法4:
this.$router.push({ path: '/user', query:{ uname:james }})
// 方法5:
this.$router.push('/user?uname=' + jsmes)
3.获取参数
this.$route.query.uname
4.特点
params和 name 的传参方式,相当于post,强制刷新参数会丢失,url中不显示参数 query和path的传参方式,相当于get,刷新参数不会丢失,url中会显示参数
5.区别
引入:
query用name或者path引入,params用name引入
刷新:
query刷新不会丢数据,params刷新会丢数据
请求:
query想到于get请求,看得见参数,params相当于post请求,看不见参数
总结
1.手写完整的 path:
this.$router.push({path: `/user/${userId}`});
获取参数:this.$route.params.userId
2.用 params 传递【刷新不丢失,路由配置了:userId】:
this.$router.push({name:'user', params:{userId: '123'}});
获取参数:this.$route.params.userId
url 形式:url 不带参数,http:localhost:8080/#/user/123
3.用 params 传递【刷新丢失】:
this.$router.push({name:'user', params:{userId: '123'}});
获取参数:this.$route.params.userId
url 形式:url 不带参数,http:localhost:8080/#/user
4.用 query 传递:
this.$router.push({path:'/user', query:{userId: '123'}});
获取参数:this.$route.query.userId
url 形式:url 带参数,http:localhost:8080/#/user?userId=123
6、路由生命周期
路由守卫分类
1.全局路由
全局路由:beforeEach、afterEach、beforeResolve
// 1.前置守卫
router.beforeEach((to, form, next) => {
// to:到哪里去
// form:从哪里来
// next() 跳转,一定要调用
// next(false) 不让走
// next(true) 继续前进
// next('/login') 走到哪里
next({ path: '/detail/2', params: {}, query: {} }) //带参数的
if (to.path === '/login' || to.path === '/reg') {
next(true)
} else {
if (没有登录过) {
next('/login')
} else {
next(true)
}
}
})
// 2.后置守卫
router.afterEach((to, form) => {
// 全局的后置守卫
})
2.组件内路由
组件内路由:beforeRouterEnter、beforeRouterUpdate、beforeRouterLeave
// 组件内部钩子
beforeRouteEnter(to, from, next) {
// ...
// 不能获取组件实例this
// 因为当守卫执行前,组件实例还没有创建
}
beforeRouteUpdate(to, form, next){
}
beforeRouteLeave(to, form, next){
// 导航离开时,调用
// 可以访问组件实例this
}
3.路由独享
路由独享:beforeEnter
// 3.路由独享守卫
{
path: '/user',
component: User,
beforeEnter: (to, from, next) => {
// ...
console.log('路由独享守卫');
if (Math.random() < .5) {
next()
} else {
next('/login')
}
}
}
路由生命周期
路由导航、keep-alive、和组件生命周期钩子结合起来的,触发顺序,假设是从a组件离开,第一次进入b组件
beforeRouteLeave:路由组件的组件离开路由前钩子,可取消路由离开。
beforeEach:路由全局前置守卫,可用于登录验证、全局路由loading等。
beforeEnter:路由独享守卫
beforeRouteEnter:路由组件的组件进入路由前钩子。
beforeResolve:路由全局解析守卫
afterEach:路由全局后置钩子
beforeCreate:组件生命周期,不能访问tAis。
created;组件生命周期,可以访问tAis,不能访问dom。
beforeMount:组件生命周期
deactivated:离开缓存组件a,或者触发beforeDestroy和destroyed组件销毁钩子。
mounted:访问/操作dom。
activated:进入缓存组件,进入a的嵌套子组件(如果有的话)。
执行beforeRouteEnter回调函数next。