vue-router以及导航守卫的应用(前端路由的概念)

目录

前端路由&&后端路由

后端路由

前端路由

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创建根实例,挂载路由

vue-router以及导航守卫的应用(前端路由的概念)

 两个基本的标签在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

导航守卫

完整的导航守卫解析流程

  1. 导航被触发。
  2. 在失活的组件里调用 beforeRouteLeave 守卫。
  3. 调用全局的 beforeEach 守卫。
  4. 在重用的组件里调用 beforeRouteUpdate 守卫 (2.2+)。
  5. 在路由配置里调用 beforeEnter
  6. 解析异步路由组件。
  7. 在被激活的组件里调用 beforeRouteEnter
  8. 调用全局的 beforeResolve 守卫 (2.5+)。
  9. 导航被确认。
  10. 调用全局的 afterEach 钩子。
  11. 触发 DOM 更新。
  12. 调用 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: truename: '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();
})

上一篇:使用vite搭建vue3项目(二)


下一篇:ROS自定义路径规划器的原理及实现