vue路由之进阶篇

本文详细讲解了Vue路由的多种传参方式,包括动态路由、函数式传参等,并介绍了html5 history模式、导航守卫、路由元信息及过渡效果的使用。通过实际代码示例,帮助读者理解Vue路由的工作原理和应用场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一.路由组件传参
router.js代码片段:

  {
    path: '/argu/:name',
    name: 'argu',
    //传入不同的参数可以进入同一个页面,实现组件的复用
    component: () => import('@/views/argu.vue'),
    props:true
  },

组件内获取路由参数的代码片段

<template>
  <div>
      {{name}}
  </div>
</template>


<script>
export default {
  props:{
    name:{
      type:String,
      // type: [String,Number]
      default:'lison'
    }
  },
  data () {
    return {
    };
  }
}
</script>

如果不是像上面那样的动态路由写法,而是下面这样的路由写法,则

  {
    path: '/about',
    name: 'about',
    component: () => import(/* webpackChunkName: "about" */ '@/views/About.vue'),
    props:{
      food:'banana'
    }
  },

组件内获取路由参数的代码片段:

<template>
  <div class="about">
    <h1>This is an about page</h1>
    {{food}}
  </div>
</template>
<script>
export default {
  props:{
    food:{
      type:String,
      default:'apple'
    }
  }
}
</script>

路由中是函数式的传参写法:
路由配置代码片段:

  {
    path: '/',
    alias: '/home_page',
    name: 'home',  
    component: Home,
    props: route => ({
      food:route.query.food
    })
    //函数式传参
  },

组件内的使用:

<template>
  <div class="home">
    <img alt="Vue logo" src="../assets/logo.png">
    <HelloWorld msg="Welcome to Your Vue.js App"/>
    <button @click="handleClick('back')">返回上一页</button>
    <button @click="handleClick('push')">返回上一页</button>
    <button @click="handleClick('replace')">替换到</button>
    <b>{{food}}</b>
  </div>
</template>

<script>
// @ is an alias to /src
import HelloWorld from '@/components/HelloWorld.vue'

export default {
  name: 'home',
  components: {
    HelloWorld
  },
  props:{
    food:{
      type:String,
      default:'apple'
    }
  }
}
</script>

二.html5 history模式

//创建路由实例
export default new Router({
  mode:'history',
  routes: routes
})

三.导航守卫
a.全局守卫

const router = new Router({
  routes
})

const HAS_LOGINED = true;
// router.beforeEach()注册全局前置守卫
router.beforeEach((to,from,next)=>{
  if(to.name !== 'login'){
    if (HAS_LOGINED) next()
    else next({name: 'login'})
    // 如果已经登录 则继续执行;如果没有登录,则进入到登录页
  }else{
    //如果当前要访问的是login页
    if(HAS_LOGINED) next({name: 'home'})
    else next()
  }
})
router.beforeResolve((to,form,next)=>{
  console.log("before resolve invoked")
  next();
})
//router.afterEach()定义路由后置(页面跳转之后)钩子
router.afterEach((to,from)=>{
  //logining=false
})
export default router

b.路由独享守卫

  //beforeEnter, 在beforeEach与beforeResolve中间执行
  {
    path: '/',
    alias: '/home_page',
    name: 'home',  
    component: Home,
    props: route => ({
      food:route.query.food
    }),
    beforeEnter: (to,from,next) => {
      if(from.name==='login') alert('这是从登录页来的')
      else alert('这不是从登录页来的')
      next()//调用next函数 才会跳转页面
    }
    //函数式传参
  },

c.组件内的守卫

export default {
  name: 'home',
  components: {
    HelloWorld
  },
  props:{
    food:{
      type:String,
      default:'apple'
    }
  },
  beforeRouteEnter (to,from,next) {
    console.log(from.name);
    //此时页面还未渲染,用this的话是获取不到vue实例的 
    console.log(this) // 这里获取不到上下文
    next(vm =>{
      //可以在next里这样
      //next里面有一个回调函数可以获取到上下文,把请求到的数据塞到vue对象中
      console.log(vm)
    })
  },
  beforeRouteLeave (to,from,next){
    //用于如果用户在当前页面进行了编辑没保存,离开当前页面时要做提示,就用到了此路由
    console.log(this) // 这里可以获取到上下文
    const leave = confirm('您确定离开?')
    if (leave) next()
    else next(false)
  },
  beforeRouteUpdate (to,from,next) {
    console.log(this) // 这里可以获取到上下文
    console.log(to.name,from.name)
  }
}
</script>

d.路由解析流程
1.导航被触发
2.在失活的组件(即将离开的页面组件)里调用离开守卫 beforeRouteLeave
3.调用全局的前置守卫beforeEach
4.在重用的组件里调用beforeRouteUpdate 或者beforeRouteEnter
5.调用路由独享的守卫 beforeEnter
6.解析异步路由组件
7.在被激活的组件(即将进入的页面组件)里面调用beforeRouteEnter
8.调用全局的解析守卫 beforeResolve
9.导航被确认
10.调用全局的后置守卫afterEach
11.触发DOM渲染
12.用创建好的实例调用beforeRouteEnter守卫里传给next的回调函数
四.路由元信息

//router/router.js代码片段
  {
    path: '/about',
    name: 'about',
    // route level code-splitting
    // this generates a separate chunk (about.[hash].js) for this route
    // which is lazy-loaded when the route is visited.
    component: () => import(/* webpackChunkName: "about" */ '@/views/About.vue'),
    props:{
      food:'banana'
    },
    meta: {
      title: '关于'
    }
  }
//router/index.js:
import {setTitle} from '@/lib/util'
router.beforeEach((to,from,next)=>{
  to.meta && setTitle(to.meta.title)
  if(to.name !== 'login'){
    if (HAS_LOGINED) next()
    else next({name: 'login'})
    // 如果已经登录 则继续执行;如果没有登录,则进入到登录页
  }else{
    //如果当前要访问的是login页
    if(HAS_LOGINED) next({name: 'home'})
    else next()
  }
})
//lib/util.js:
// 与业务有关的方法代码
export const setTitle = (title) =>{
    window.document.title = title || 'admin'
}

五.过渡效果
app.vue:

    <!-- 如果要对多个视图做过渡效果要用到 transition group -->
    <transition-group name="router">
      <!-- name还可以设成动态绑定的值 :name="routerTransition" -->
      <router-view key="default"/>
      <!-- 命名路由——页面要展示多个不同的视图时 -->
      <router-view key="email" name="email"/>
      <router-view key="tel" name="tel"/>
    </transition-group>

	<script>
	export default {
	  data(){
	    return{
	      routerTransition:''
	    }
	  },
	  watch:{
	    '$route'(to){
	      to.query&&to.query.transitionName&&(this.routerTransition=to.query.transitionName)
	    }
	  }
	}
	</script>
    <style lang="less">
	// router使用transition的name的值
	// 页面进入时的效果
	.router-enter{
	  opacity: 0;
	}
	.router-enter-active{
	  transition: opacity 1s ease;
	}
	.router-enter-to{
	  opacity: 1;
	}
	// 页面离开时的效果
	.router-leave{
	  opacity: 1;
	}
	.router-leave-active{
	  transition: opacity 1s ease;
	}
	.router-leave-to{
	  opacity: 0;
	}
	</style>

注:vue路由传参query和params的区别:
https://blog.csdn.net/airdark_long/article/details/78272817
https://www.jianshu.com/p/45ee7a6bdc0c

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值