vue-router以及导航守卫的应用(前端路由的概念)
作者:互联网
目录
前端路由&&后端路由
路由的功能包括路由(映射)和转发
后端路由
后端渲染:相当于把url地址传给服务器,而服务器会根据html+css+后端语言进行网页渲染,然后再返回前端,内容包括HTML+css,当然是包含数据的HTML。
后端路由的步骤:
1:一个页面有对应的网址也就是url
2:url发送到服务器进行匹配,交给一个controller进行处理
3:controller进行各种处理后返回html数据,返回给前端
4:完成一个i/o操作
前端路由
前端渲染:浏览器中网页显示的大部分内容都是由js在浏览器执行来进行渲染的,当输入某些具体的url地址时,会先去静态资源服务器请求对应的html+css+js代码并下载,然后在去提供API接口的服务端获取数据,通过前端ajax转换后,最终渲染出来。
SPA页面(单页富应用):SPA最主要的特点就是在前后端分离的基础上加了一层前端路由,整个网页只有一个html页面。在SPA中,静态资源服务器内只含有一个html文件,甚至只有一套html+css+js文件,当url发生变化时,会先向js中找到对应的相关代码,并分离进而渲染在客户端。
vue默认开发的就是典型的单页面应用,只有一个html页面在public文件夹下。
前端路由:在前端处理url与页面之间的映射关系。
前端路由的核心是:改变url但不进行整体的页面刷新,没有向服务器进行请求而是使用js。
如何改变url而不进行页面刷新?
1、URL的hash
URL的hash也就是锚点,本质上是改变window.location的href属性。
我们可以通过直接赋值location.hash来改变href,但是页面不发生刷新。
2、HTML5的history
history.pushState({},'','home')
history.pushState相当于栈的操作,先进后出,弹栈和入栈的操作。
history.pushState入栈;
history.back()出栈;
history.go(-1) 相当于 history.back();
history.forward 相当于history.go(1);
history.replaceState():不能返回;
————————————————
版权声明:本文为CSDN博主「哪 吒」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/guorui_java/article/details/120626879
vue-router
上手
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="./vue.min.js" type="text/javascript" charset="utf-8"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
</head>
<body>
<div id="app">
<p>
<router-link to="/foo">go to foo</router-link>
<router-link to="/bar">go to bar</router-link>
</p>
<router-view></router-view>
</div>
<script type="text/javascript">
//定义路由组件
var Foo = {template:'<div>foo</div>'};
var Bar = {template:'<div>bar</div>'};
//定义路由
const routes = [
{path:'/foo' , component:Foo},
{path:'/bar' , component:Bar},
]
//创建router实例,传routes配置
const router = new VueRouter({
routes:routes
})
//创建根实例并挂载div
const app = new Vue({
router
}).$mount("#app")
</script>
</body>
</html>
这里实现了一个简单的路由,有以下步骤:
1定义两个路由组件,当中仅有模板
2定理路由配置对象,创建路径与组件的映射关系
3创建router实例,传入配置
4创建根实例,挂载路由
两个基本的标签在html当中使用:router-link,router-view
router-link:
tag:tag可以指定router-link之后渲染成什么组件,比如<router-link tag='button'></router-link>,此时就是一个button了;
replace:增加replace属性,就相当于replaceState;
class:可以为标签增加样式,比如选中的会自动赋值router-link-active;
active-class=“active”:选中的;也可以在router组件中配置linkActiveClass: 'active';
————————————————
版权声明:本文为CSDN博主「哪 吒」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/guorui_java/article/details/120626879
router-view:
根据路由映射的组件显示的区域
路由的组件化开发:
在组件化开发里,Vue router都是在router.js统一管理,使用AMD规范将组件引入进来
import downApp from '@/components/downApp.vue'
随后引用Router,再将接口暴露出去,一般使用webpack
构建项目的时候就已经做好这个步骤了
Vue.use(Router)
export default new Router({
//历史模式,也就是将页面上链接的主页前面的无用信息过滤掉
mode:'history',
routers:[{}...]
})
参数分别有path(路径),name(可选,路由名),alias(可选,别名),component(组件名),meta(可选,元数据,多用在导航守卫上),redirect(可选,重定向,多用于导航守卫返回原页面)
组件化开发的index.js大致分为五步:
1,import组件
2,use(Router)因为它是一个插件,所以可以通过Vue.use()来安装路由功能
3,创建路由配置对象
4,创建路由实例并传入路由配置
5,export default router
组件化开发的所有组件基本上放在views当中
组件化开发最终在main.js当中导入路由,并在创建根实例的时候导入即可
嵌套路由
借助 vue-router
,使用嵌套路由配置,就可以很简单地表达这种关系。
接着上节创建的 app:
<div id="app">
<router-view></router-view>
</div>
const User = {
template: '<div>User {{ $route.params.id }}</div>'
}
const router = new VueRouter({
routes: [{ path: '/user/:id', component: User }]
})
这里的 <router-view>
是最顶层的出口,渲染最高级路由匹配到的组件。同样地,一个被渲染组件同样可以包含自己的嵌套 <router-view>
。例如,在 User
组件的模板添加一个 <router-view>
:
const User = {
template: `
<div class="user">
<h2>User {{ $route.params.id }}</h2>
<router-view></router-view>
</div>
`
}
要在嵌套的出口中渲染组件,需要在 VueRouter
的参数中使用 children
配置:
const router = new VueRouter({
routes: [
{
path: '/user/:id',
component: User,
children: [
{
// 当 /user/:id/profile 匹配成功,
// UserProfile 会被渲染在 User 的 <router-view> 中
path: 'profile',
component: UserProfile
},
{
// 当 /user/:id/posts 匹配成功
// UserPosts 会被渲染在 User 的 <router-view> 中
path: 'posts',
component: UserPosts
}
]
}
]
})
要注意,以 /
开头的嵌套路径会被当作根路径。 这让你充分的使用嵌套组件而无须设置嵌套的路径。
你会发现,children
配置就是像 routes
配置一样的路由配置数组,所以呢,你可以嵌套多层路由。
此时,基于上面的配置,当你访问 /user/foo
时,User
的出口是不会渲染任何东西,这是因为没有匹配到合适的子路由。如果你想要渲染点什么,可以提供一个 空的 子路由:
const router = new VueRouter({
routes: [
{
path: '/user/:id',
component: User,
children: [
// 当 /user/:id 匹配成功,
// UserHome 会被渲染在 User 的 <router-view> 中
{ path: '', component: UserHome }
// ...其他子路由
]
}
]
})
转自官方文档
路由的懒加载
当打包构建应用时,JavaScript包会变得非常大,影响页面加载。
如果我们能把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应组件,这样就更加高效了。
懒加载的方式:
(1)结合Vue的异步组件和Webpack的代码分析
const Home = resolve => { require.ensure(['../components/Home.vue'],
() => { resolve(require('../components/Home.vue')) })};
(2)amd写法
const About = resolve => require(['../components/About.vue'], resolve);
(3)在ES6中,我们可以有更加简单的写法来组织Vue异步组件和Webpack的代码分割
const Home = () => import('../components/Home.vue')
demo:
// import Home from '../components/Home'
// import About from '../components/About'
// import User from '../components/User'
// 懒加载方式
const Home = () => import('../components/Home')
const About = () => import('../components/About')
————————————————
版权声明:本文为CSDN博主「哪 吒」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/guorui_java/article/details/120626879
导航守卫
完整的导航守卫解析流程
- 导航被触发。
- 在失活的组件里调用
beforeRouteLeave
守卫。 - 调用全局的
beforeEach
守卫。 - 在重用的组件里调用
beforeRouteUpdate
守卫 (2.2+)。 - 在路由配置里调用
beforeEnter
。 - 解析异步路由组件。
- 在被激活的组件里调用
beforeRouteEnter
。 - 调用全局的
beforeResolve
守卫 (2.5+)。 - 导航被确认。
- 调用全局的
afterEach
钩子。 - 触发 DOM 更新。
- 调用
beforeRouteEnter
守卫中传给next
的回调函数,创建好的组件实例会作为回调函数的参数传入。
全局守卫
router.beforeEach((to, from, next) => {
console.log(to) => // 到哪个页面去?
console.log(from) => // 从哪个页面来?
next() => // 一个回调函数
}
router.afterEach(to,from) = {}
每个守卫方法接收三个参数:
-
to: Route
: 即将要进入的目标 路由对象 -
from: Route
: 当前导航正要离开的路由 -
next: Function
: 一定要调用该方法来 resolve 这个钩子。执行效果依赖next
方法的调用参数。-
next()
: 进行管道中的下一个钩子。如果全部钩子执行完了,则导航的状态就是 confirmed (确认的)。 -
next(false)
: 中断当前的导航。如果浏览器的 URL 改变了 (可能是用户手动或者浏览器后退按钮),那么 URL 地址会重置到from
路由对应的地址。 -
next('/')
或者next({ path: '/' })
: 跳转到一个不同的地址。当前的导航被中断,然后进行一个新的导航。你可以向next
传递任意位置对象,且允许设置诸如replace: true
、name: 'home'
之类的选项以及任何用在 router-link 的 to prop 或 router.push 中的选项。 -
next(error)
: (2.4.0+) 如果传入next
的参数是一个Error
实例,则导航会被终止且该错误会被传递给 router.onError() 注册过的回调。
-
确保 next
函数在任何给定的导航守卫中都被严格调用一次。它可以出现多于一次,但是只能在所有的逻辑路径都不重叠的情况下,否则钩子永远都不会被解析或报错。
路由独享守卫
const router = new VueRouter({
routes: [
{
path: '/foo',
component: Foo,
beforeEnter: (to, from, next) => {
// ...
}
}
]
})
参数与全局守卫相同
组件局部守卫
const Foo = {
template: `...`,
beforeRouteEnter(to, from, next) {
// 在渲染该组件的对应路由被 confirm 前调用
// 不!能!获取组件实例 `this`
// 因为当守卫执行前,组件实例还没被创建
},
beforeRouteUpdate(to, from, next) {
// 在当前路由改变,但是该组件被复用时调用
// 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
// 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
// 可以访问组件实例 `this`
},
beforeRouteLeave(to, from, next) {
// 导航离开该组件的对应路由时调用
// 可以访问组件实例 `this`
}
}
beforeRouteEnter
守卫 不能 访问 this
,因为守卫在导航确认前被调用,因此即将登场的新组件还没被创建。
不过,你可以通过传一个回调给 next
来访问组件实例。在导航被确认的时候执行回调,并且把组件实例作为回调方法的参数。
一个守卫的实例:
该demo是用于验证当前是否有用户登录,如果没有则会强制跳转到login界面
router.beforeEach((to,from,next)=>{
let user=window.localStorage.getItem("user");//读取是否有登录信息
let token=window.localStorage.getItem("token");
if(user!=null&&token!=null && to.path == '/login'){//如果已经登录并且跳转的路径为login,则不允许
next('/home')
}
else if(to.path == '/login' || to.path == '/register'){//如果没有登录跳转的路径为login,则放行
next();
}else if(user===null&&token===null){//如果要去的路径不是login,并且没有登陆,则强行跳转登陆窗口
alert('您还没有登录,请先登录');
next('/login');
}
else next();
})
标签:vue,const,next,守卫,组件,router,路由 来源: https://blog.csdn.net/weixin_46104231/article/details/121799307