1.简介
SPA(Single Page Application)
- Ajax前端渲染(前端渲染提高性能,但是不支持浏览器的前进后退操作)
- SPA(Single Page Application)单页面应用程序:整个网站只有一个页面,内 容的变化通过Ajax局部更新实现、同时支持浏览器地址栏的前进和后退操作
- SPA实现原理之一:基于URL地址的hash(hash的变化会导致浏览器记录访问历 史的变化、但是hash的变化不会触发新的URL请求
- 在实现SPA过程中,最核心的技术点就是前端路由
前端路由
- 概念:根据不同的用户事件,显示不同的页面内容
- 本质:用户事件与事件处理函数之间的对应关系
2 路由组件传递参数
$route
与对应路由形成高度耦合,不够灵活,所以可以使用props
将组件和路由解耦
第一种情况:
props的值为布尔类型
const router = new VueRouter({
routes: [
// 如果 props 被设置为 true,route.params 将会被设置为组件属性
{ path: '/user/:id', component: User, props: true }
]
})
const User = {
props: ['id'], // 使用 props 接收路由参数
template: '<div>用户ID:{{ id }}</div>' // 使用路由参数
}
在定义路由规则的时候,为其添加了props
属性,并将其值设置为true
.那么在组件中就可以通过props:['id']
的形式来获取对应的参数值。
3 路由守卫
Vue-router
中的路由守卫,主要是对其内容进行保护,如果没有对应的权限,则不允许访问。
我们首先来看一下全局守卫,也就是所有的路由都会经过全局守卫来进行检测。
//实现全局守卫
router.beforeEach((to, from, next) => {
//to:去哪个页面,from来自哪个页面,next继续执行.
//判断哪个路由需要进行守卫,这里可以通过元数据方式
if (to.meta.auth) {
if (window.isLogin) {
next();
} else {
next("/login?redirect=" + to.fullPath);
}
} else {
next();
}
});
在上面的代码中,创建了路由守卫,但是需要判断的是需要对哪个路由进行守卫,这里就是通过元数据来进行判断的。如果所跳转到的路由有元数据,并且对应的auth
属性为true
表明是需要进行守卫的,那么下面就需要校验用户是否登录,这里是通过判断否window.isLogin
的值是否为true
来进行判断的(这里简化了操作,实际应用中应该存储到sessionStorage
),如果条件成立则表明用户登录,就继续访问用户希望访问到的页面,否则跳转到登录页面,而且将用户希望访问的页面地址也传递到了登录页面,这样用户登录成功后,可以直接跳转到要访问的页面。
如果没有元数据,则继续访问用户要访问的页面。
4.addRoutes动态路由添加
在前面的案例中,我们都是将路由定义好,然后通过路由守卫来判断,某个用户是否登录,从而决定能否访问某个路由规则对应的组件内容。
但是,如果某些路由规则只能用户登录以后才能够访问,那么我们也可以不用提前定义好,而是在登录后,通过addRoutes
方法为其动态的添加。
首先这里需要,还需要全局的路由守卫来进行校验判断,只不过这里全局路由守卫的逻辑发生了变化。
router.beforeEach((to, from, next) => {
//to:去哪个页面,from来自哪个页面,next继续执行.
if (window.isLogin) {
//用户已经登录
if (to.path === "/login") {
// 用户已经登录了,但是又访问登录页面,这里直接跳转到用户列表页面
next("/");
} else {
//用户已经登录,并且访问其它页面,则运行访问
next();
}
} else {
//用户没有登录,并且访问的就是登录页,则运行访问登录页
if (to.path === "/login") {
next();
} else {
//用户没有登录,访问其它页面,则跳转到登录页面。
next("/login?redirect=" + to.fullPath);
}
}
});
下面对登录组件进行修改
const Login = {
data() {
return {
isLogin: window.isLogin,
};
},
template: `<div>
<button @click="login" v-if="!isLogin">登录</button>
<button @click="logout" v-else>注销</button>
</div>`,
methods: {
login() {
window.isLogin = true;
if (this.$route.query.redirect) {
//动态添加路由:
this.$router.addRoutes([
{
path: "/",
component: App,
redirect: "/users",
children: [
{
path: "/users",
component: Users,
meta: {
auth: true,
},
// beforeEnter(to, from, next) {
// if (window.isLogin) {
// next();
// } else {
// next("/login?redirect=" + to.fullPath);
// }
// },
},
{ path: "/userinfo/:id", component: UserInfo, props: true },
{ path: "/rights", component: Rights },
{ path: "/goods", component: Goods },
{ path: "/orders", component: Orders },
{ path: "/settings", component: Settings },
],
},
]);
this.$router.push(this.$route.query.redirect);
} else {
this.$router.push("/");
}
},
logout() {
this.isLogin = window.isLogin = false;
},
},
};
在登录成功后,通过addRoutes
方法动态的添加路由规则,也就是所添加的路由规则只能是在登录以后才能够访问,所以全局守卫的判断条件发生了变化,不在判断是否有元数据,而只是判断是否登录。如果登录了,想访问上面的路由规则,则运行访问,如果没有登录则不允许访问。
5. 路由组件缓存
利用keepalive
做组件缓存,保留组件状态,提高执行效率。
<keep-alive include="home">
<router-view></router-view>
</keep-alive>
使用include
或者exclude
时要给组件设置name
(这个是组件的名称,组件的名称通过给组件添加name
属性来进行设置)
当我们进行路由切换的时候,对应的组件会被重新创建,同时数据也会不断的重新加载。
如果数据没有变化,就没有必要每次都重新发送异步请求加载数据
应用场景
如果未使用keep-alive组件,则在页面回退时仍然会重新渲染页面,触发created钩子,使用体验不好。 在以下场景中使用keep-alive组件会显著提高用户体验,菜单存在多级关系,多见于列表页+详情页的场景如:
- 商品列表页点击商品跳转到商品详情,返回后仍显示原有信息
-
订单列表跳转到订单详情,返回,等等场景。
生命周期: activated
和deactivated
会在keep-alive
内所有嵌套的组件中触发 如:B页面是缓存页面 当A页面跳到B页面时,B页面的生命周期:activated(可在此时更新数据) B页面跳出时,触发deactivated B页面自身刷新时,会触发created-mouted-activated
6、Hash模式与History模式
1 Hash模式与History模式区别
前端路由中,不管是什么实现模式,都是客户端的一种实现方式,也就是当路径发生变化的时候,是不会向服务器发送请求的。
如果需要向服务器发送请求,需要用到ajax
方式。
两种模式的区别
首先是表现形式的区别
Hash
模式
https://www.baidu.com/#/showlist?id=22256
hash
模式中路径带有#
, #
后面的内容作为路由地址。可以通过问号携带参数。
当然这种模式相对来说比较丑,路径中带有与数据无关的符号,例如#
与?
History
模式
https://www.baidu.com/showlist/22256
History
模式是一个正常的路径的模式,如果要想实现这种模式,还需要服务端的相应支持。
下面再来看一下两者原理上的区别。
Hash
模式是基于锚点,以及onhashchange
事件。
通过锚点的值作为路由地址,当地址发生变化后触发onhashchange
事件。
History
模式是基于HTML5
中的History API
也就是如下两个方法
history.pushState( )
IE10
以后才支持
history.replaceState( )
7.Vue Router原理
Hash
模式的工作原理。
- ·
URL
中#
后面的内容作为路径地址,当地址改变的时候不会向服务器发送请求,但是会触发hashchange
事件。 - 监听
hashchange
事件,在该事件中记录当前的路由地址,然后根据路由地址找到对应组件。 - 根据当前路由地址找到对应组件重新渲染。
History
模式
- 通过
history.pushState()
方法改变地址栏,并且将当前地址记录到浏览器的历史记录中。当前浏览器不会向服务器发送请求 - 监听
popstate
事件,可以发现浏览器历史操作的变化,记录改变后的地址,单击前进或者是后退按钮的时候触发该事件 - 根据当前路由地址找到对应组件重新渲染