vue-router路由深入理解(路由跳转和路由传参)

这篇文章主要讲路由跳转和路由传参,声明式导航和编程式导航的跳转和传参的区别,开始先回顾配置路由的几个步骤。

一、使用路由的4步

定义路由组件
注册路由
引入路由
路由跳转

1) 定义路由组件

src/pages/Home/index.vue
src/pages/Login/index.vue

2) 配置路由/ 注册路由

src/router/index.js

// 配置路由的地方
import Vue from 'vue'
import VueRouter from 'vue-router'
// 使用插件
Vue.use(VueRouter)
// 引入路由组件
import Home from '@/pages/Home'
import Login from '@/pages/Login'
// 配置路由
export default new VueRouter({
  routes: [
    {
      path: '/home',
      component: Home
    }, 
    {
      path: '/login',
      component: Login
    },
     // 重定向在项目跑起来的时候,访问/,立马让它定向到首页
    {
      path: '*', // 或者 path: '/'
      component: Home
    },
  ]
})

3) 使用路由(文件夹),入口文件引入和注册路由

  • main.js
import Vue from 'vue'
import App from './App.vue'
// 引入路由
import router from '@/router'
Vue.config.productionTip = false

new Vue({
  render: h => h(App),
  // 注册路由:底下的写法KV一致省略V【router小写的】
  // 注册路由信息:当这里书写router的时候。组件身上都拥有$route,$router属性
  router
}).$mount('#app')

4)路由跳转

  • App.vue
<template>
  <div>
    <!-- 路由组件出口的地方 -->
    <router-view></router-view>
  </div>
</template>

以上四步就可以实现在地址栏手动输入路由展示对应的路由组件

路由组件和非路由组件的区别

1.路由组件一般放置在pages或者views文件夹,非路由组件一般放置在components文件夹中
2.路由组件一般需要在router文件夹中进行注册
3.注册完路由,不管路由组件还是非路由组件身上都有 r o u t e 和 route和 routerouter属性

$route和$router

$route:一般获取路由信息【路径、query、params等等】
$router:一般进行编程式导航进行路由跳转【push|replace】

二、路由的跳转

声明式导航:声明式导航能做的,编程式导航都能做
编程式导航:除了可以进行路由跳转,还可以做一些其他的业务逻辑

声明式导航

例子:原本a标签跳转改成router-link跳转,必须要有to属性注意样式还在

  • 例1
<a href="###">登录</a>

改成

<router-link to="/login">登录</router-link>
  • 例2
    target是打开新的网页
<a  class="logo" href="###" title="尚品汇" target="_blank">
  <img src="./images/logo.png" alt="" />
</a>

改成声明式路由导航

<router-link class="logo" to="/home">
  <img src="./images/logo.png" alt="" />
</router-link>  

编程式导航

  • 比如元素上加点击事件
<div @click="gotoSearch()">跳转</div>
gotoSearch() {
    this.$router.push(/search)
}

三、路由元信息

可以根据组件身上的$route获取当前路由的信息,通过路由路径判断Footer显示和隐藏
配置路由的时候,可以给路由添加路由元信息【meta】,路由需要配置对象,它的key不能乱写

  • router/index.js
routes: [
    {
      path: '/home',
      component: Home,
      meta: {show:true}
    }, 
    {
      path: '/login',
      component: Login,
       meta: {show:false}
    },
     ...
  ]
  • App.vue

Header组件和Footer组件 都是非路由组件

<template>
  <div>
    <Header />
    <!-- 路由组件出口的地方 -->
    <router-view></router-view>
    <!-- 在Home与Search可见的,但是Login|Register不可见 -->
    <!-- 利用路由元信息解决当前问题好处:一行代码就可以解决 -->
    <Footer v-show="$route.meta.isShow" />
  </div>
</template>

四、路由传参

params参数:路由需要占位,属于URL当中一部分
query参数:路由不需要占位,写法类似于ajax当中query参数,queryString /home?k=v&kv=,不需要占位

  • demo效果

在这里插入图片描述

query参数–三种形式直接传

  • views/Header/index.vue
<template>
  <div>
    <h3>Header组件</h3>
    <input type="text" v-model="keyword" />
    <button type="button" @click="goSearch">搜索</button>
  </div>
</template>
<script>
export default {
  data() {
    return {
      keyword: ''
    }
  },
  methods: {
    goSearch() {
      // this.$router.push('/search') // 不传参
      // 路由传递参数
      // 第一种:字符串形式
      // this.$router.push("/search/" + this.keyword + "?k=" + this.keyword.toUpperCase())
      // 第二种:模板字符串
      // this.$router.push(`/search/${this.keyword}?k=${this.keyword.toUpperCase()}`)
      // 第三种:对象--常用
      this.$router.push({name:'search', params: {keyword: this.keyword}, query: {k: this.keyword.toUpperCase()}})
    }
  }
}
</script>
  • views/Search/index.vue

params参数–字符串形式和模板字符串–额外配置

  • router/index.js配置路由时,加/:keyword
 {
      path: '/search/:keyword',
      component: Search,
      meta: {show: true}
 },

params参数–对象形式–额外配置

  • router/index.js配置路由时,加name
 {
      path: '/search',
      component: Search,
      meta: {show: true},
      name: 'search'
 },
  • 如果没配置,会报错如下

在这里插入图片描述

五、路由传递参数相关面试题

1:路由传递参数(对象写法)path是否可以结合params参数一起使用?
2:如何指定params参数可传可不传?
3:params参数可以传递也可以不传递,但是如果传递是空串,如何解决?
4:如果指定name与params配置, 但params中数据是一个"", 无法跳转,路径会出问题
5: 路由组件能不能传递props数据?

1:路由传递参数(对象写法)path是否可以结合params参数一起使用?

答:路由跳转的时候,对象的写法可以是name、path形式,但是需要注意的是,path这种写法不能和params参数一起使用,不能这样书写,程序会崩掉
根据上面demo代码测试错误写法

this.$router.push({path:'/search', params: {keyword: this.keyword}, query: {k: this.keyword.toUpperCase()}})

报错如下
在这里插入图片描述

2:如何指定params参数可传可不传?

比如:配置路由的时候,占位了(params参数),但是路由跳转的时候就不传递。路径会出现问题
http://localhost:8080/#/?k=QWE
解决办法:如何指定params参数可以传递或者不传递,
在配置路由的时候,在占位的后面加上一个问号【params可以传递或者不传递】

  • router/index.js配置路由时,在/:keyword后加?
 {
      path: '/search/:keyword?',
      component: Search,
      meta: {show: true}
 },
  • 效果:
http://localhost:8080/#/search?k=QWE

3:params参数可以传递也可以不传递,但是如果传递是空串,如何解决?

使用undefined解决,如果传递是空串,让传递的值变成undefined:params参数可以传递、不传递(空字符串)

this.$router.push({name:'search', params: {keyword: '' || undefined}, query: {k: this.keyword.toUpperCase()}})

4:如果指定name与params配置, 但params中数据是一个""

无法跳转,路径会出问题

5: 路由组件能不能传递props数据?

能(用得少)

布尔值写法(只能传递params参数)

  • router/index.js配置路由时,加props: true,让props成为路由的属性
 {
      path: '/search/:keyword?',
      component: Search,
      meta: {show: true},
      props: true},
  • 接收的路由组件里
    Search/index.vue
    和普通组件接收一样,模板渲染使用{{keyword}}
props: ['keyword']

在这里插入图片描述

对象写法

  • router/index.js配置路由时,加些额外参数
 {
      path: '/search/:keyword?',
      component: Search,
      meta: {show: true},
      props: true,
      props: {a:1, b:2}
 },
  • 接收的路由组件里Search/index.vue

props和普通组件接收一样,模板渲染使用{{keyword}} {{a}} {{b}}

props: ['keyword''a','b']

函数写法

可以将params、query参数,通过props传递给路由组件

props:($route) => {
	return {keyword: $route.params.keyword, k: $route.query.k}
}

六、重写push和replace方法

理解

1.编程式导路由跳转到当前路由(参数不变),多次执行会抛出NavigationDuplicated的警告错误?
路由跳转有两种形式:声明式导航、编程式导航
声明式导航没有这类问题,因为vue-router底层已经处理好了

  • 1.1为什么编程式导航进行路由跳转的时候,就会有这种警告错误?
    原因:“vue-router”: “^3.5,3”,最新的vue-router引入promise
    理解:
function push() {
	return new Promise((resolve, reject) => {
	
	})
}

所以我们需要给promise传入成功或者失败的状态,才能捕获这次的异常

  • 1.2解决思路:通过push方法传递相应的成功、失败的回调函数,可以捕获到当前错误,可以解决。
  • 1.3通过底部的代码,可以实现解决错误
this.$router.push({name:"search", params:{keyword: this.keyword}, query: {k: this.keyword.toUpperCase()}}, ()=> {}, ()=> {})

这种写法,治标不治本,将来在别的组件当中push|replace,编程式导航还是有类似错误。

  • 1.4

this:是当前组件(search组件)实例
this. r o u t e r 属 性 : 当 前 的 这 个 属 性 , 属 性 值 V u e R o u t e r 类 的 一 个 实 例 , 当 在 入 口 文 件 注 册 路 由 的 时 候 , 给 组 件 实 例 添 加 router属性:当前的这个属性,属性值VueRouter类的一个实例,当在入口文件注册路由的时候,给组件实例添加 routerVueRouterrouter| r o u t e 属 性 控 制 台 打 印 c o n s o l e . l o g ( t h i s . route属性 控制台打印console.log(this. routeconsole.log(this.router),可以看出
push是在this.$router的原型上,所以push是VueRouter类的一个实例

在这里插入图片描述
理解push是VueRouter类的一个实例

  • VueRouter
 function VueRouter() {
 }
  • 原型对象的方法
 VueRouter.prototype.push = function() {
   // 函数的上下文为VueRouter类的一个实例
 }

let $router = new VueRouter()

$router.push(xxx)

this.$router.push()

所以我们要重写VueRouter.prototype.push的方法

重写push和replace方法–代码

在router/index.js里console.log(VueRouter.prototype)

  • router/index.js

思路:使用原本的push|replace方法,传原本的参数this实例,和location, 判断是否有传状态参数,有传;没有传。

// 先把VueRouter原型对象的push,先保存一份
let originPush = VueRouter.prototype.push
let originReplace = VueRouter.prototype.replace

// 重写push|replace
// 第一个参数:告诉原来push方法,你往哪里跳转(传递哪些参数)
VueRouter.prototype.push = function(location, resolve, reject) {
  if(resolve && reject) {
		// call || appply 区别
		// 相同点, 都可以调用函数一次,都可以篡改函数的上下文一次
		// 不同点: call与apply传递参数:call传递参数用逗号隔开,apply方法执行,传递数组
		originPush.call(this, location, resolve, reject)
   } else {
		originPush.call(this, location, () => {}, () => {} )
   }
}

VueRouter.prototype.replace = function(location, resolve, reject) {
  if(resolve && reject) {
		originReplace.call(this, location, resolve, reject)
   } else {
		originReplace.call(this, location, () => {}, () => {} )
   }
}
  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值