vue-router@3的使用

Router day01

1. 对路由的理解

  1. 概念: 一个路由(route)是一组映射关系(key:value)。
  2. 作用:前端路由是为了实现多组件切换(SPA应用)。
  3. 备注:路由需要路由器(router)进行管理。

2. 准备一个效果

vue-router@3的使用_第1张图片

第一步:参考 about.htmlhome.html,把App结构写好。

第二步:编写两个组件: About.vueHome.vue

第三步:找到App中的导航区、展示区,熟悉一下它们位置。

3. 搭建路由环境

  1. 安装vue-router,命令:npm i vue-router@3

    备注:在vue2中要用vue-router@3vue3中要用vue-router@4

  2. 创建src/router/index.js,配置路由器:

    // 该文件主要用于:创建并暴露一个真正的路由器
    import Vue from 'vue'
    // 引入VueRouter
    import VueRouter from 'vue-router'
    
    // 安装VueRouter插件
    Vue.use(VueRouter)
    
    // 创建并暴露一个路由器
    export default new VueRouter({})
    
  3. 创建vm时传入路由器配置(操作的是:src\main.js

    import Vue from 'vue'
    import App from './App'
    //引入路由器
    import router from './router' 
    
    Vue.config.productionTip = false
    
    new Vue({
    	el:'#root',
    	render: h => h(App),
    	router //此处传入路由器
    })
    
  4. 路径中出现#,开发者工具中有Routes选项,所有的vcvm身上均有了$router$route,就是配置成功了。

4. 基本切换

  1. src/router/index.js,配置路由规则:

    import Home from '@/components/Home'
    import About from '@/components/About'
    
    // 创建并暴露一个路由器
    export default new VueRouter({
        //routes中配置一组一组的路由规则
    	routes:[ 
    		{ path:'/about',component:About },
    		{ path:'/home',component:Home }
    	]
    })
    
  2. 跳转路由

    
    <router-link class="list-group-item" to="/about">
      About
    router-link>
    
  3. 指定展示位置

    <router-view>router-view><router-view/>
    

5. 路由器工作模式

  1. history(美观,兼容性略差,后期上线部署时,服务器要做对应处理)—— 前台项目推荐使用

  2. hash(不美观,带#,但兼容性较好)—— 一般后台管理系统推荐使用。

  3. 如何配置? —— 创建路由器的时候添加一个mode属性

    let router = new VueRouter({
      mode:'history', //常用值:history、hash
      //....
    })
    

6. 高亮效果

使用active-class可以指定高亮的类名


<router-link class="list-group-item" active-class="xxxxxx" to="/about">
  About
router-link>

7. to属性的两种写法


<router-link active-class="active" to="/about">Aboutrouter-link>


<router-link active-class="active" :to="{path:'/about'}">Aboutrouter-link>

8. 两个注意点

  1. 路由组件通常存放在pagesviews文件夹,一般组件通常存放在components文件夹。

  2. 通过点击导航,视觉效果上“消失” 了的路由组件,默认是被销毁掉的,需要的时候再去挂载

9. 二级路由

  1. 编写Home的两个子组件:News.vueMessage.vue

  2. 配置路由规则,使用children配置项:

    /*******/
    	{
    		path:'/home',
    		component:Home,
        	//通过children配置子级路由
    		children:[
    			{
    				path:'news', //此处要写news!不是/news,
    				component:News
    			},
    			{
    				path:'message',//此处要写message!不是/message,
    				component:Message
    			}
    		]
    	}
    /*******/
    
  3. 跳转路由(记得要加完整路径):

    <router-link to="/home/news">Newsrouter-link>
    
    <router-link :to="{path:'/home/news'}">Newsrouter-link>
    
  4. 记得去Home组件中预留一个

    <template>
    	<div>
    		<h2>我是Home的内容h2>
    		
    		<ul class="nav nav-tabs">
    			<li>
    				<router-link to="/home/news">Newsrouter-link>
    			li>
    			<li>
    				<router-link to="/home/message">Messagerouter-link>
    			li>
    		ul>
    		
    		<div>
    			<router-view/>
    		div>
    	div>
    template>
    

10. 样式丢失问题

当出现子级路由时,刷新页面会造成第三方样式丢失的问题,三种解决方案如下:

  1. public/index.html中引入样式时的路径修改一下,将 ./ 改为 /。(最推荐)
  2. public/index.html中引入样式时的路径修改一下,将 ./ 改为 <%= BASE_URL %>。(推荐)
  3. 将路由器的工作模式调整为hash模式(不推荐)

day02

1.命名路由

  1. 可以简化:路由跳转、路由传参(接下来就要讲了)。

  2. 具体使用步骤:

    1. 给路由命名:

      const router = new VueRouter({
        mode:'history',
        //routes用于配置一组一组的路由规则
        routes:[
          {
            name:'guanyu',
            path:'/about',
            component:About
          },
          {
            name:'zhuye',
            path:'/home',
            component:Home,
            children:[
              {
                name:'xinwen',
                path:'news',
                component:News
              },
              {
                name:'xiaoxi',
                path:'message',
                component:Message,
              }
            ]
          }
        ]
      })
      
    2. 跳转路由:

      
      跳转
      
      
      跳转
      

2. $route 与 $router

  1. 组件实例的$route属性:存储着当前路由信息(路径、参数、规则名字…后期会用到这里很多的属性)。

  2. 组件实例的$router属性:整个应用的路由器,后期可以通过它 控制路由跳转

3. 准备一个三级路由

  • 需求:点击某个消息后,展示详情组件。
  • 具体操作:
    • 第一步:准备一个Detail组件。
    • 第二步:去指定路由规则。
    • 第三步:去Message组件中编写:router-linkrouter-view

4. 路由query参数

4.1. 基本使用

  • 传递参数

    <!-- 跳转并携带query参数(to的字符串写法) -->
    <router-link to="/home/message/detail?a=1&b=2&content=欢迎你">
    	跳转
    </router-link>
    				
    <!-- 跳转并携带query参数(to的对象写法) -->
    <router-link 
      :to="{
        //name:'xiangqing', //用name也可以跳转
        path:'/home/message/detail',
        query:{
          id:m.id,
          title:m.title,
          content:m.content
        }
      }"
    >
      {{m.title}}
    </router-link>
    
  • 接收参数:

    this.$route.query.xxx
    

4.2.注意事项

  • query参数,没什么坑,唯一要注意的是:参数的值尽可能别是对象;参数若是对象,跳转传递时没问题,但会造成刷新时参数变为[object Object]
  • 备注:路由组件初次呈现是挂载,后期参数发生变化会更新。

5. 路由params参数

5.1 基本使用

  • 第一步:在路由规则中,声明接收params参数:

    {
    	path:'/home',
    	component:Home,
    	children:[
    		{
    			path:'news',
    			component:News
    		},
    		{
    			component:Message,
    			children:[
                    {
                      name:'xiangqing',
                      path:'detail/:id/:title/:content',
                      component:Detail
                    }
          		]
    		}
    	]
    }
    
  • 第二步:传递params参数

    
    <router-link :to="`/home/message/detail/${m.id}/${m.title}/${m.content}`">
      {{m.title}}
    router-link>
    
    
    <router-link 
    	:to="{
    		name:'xiangqing',
    		params:{
    			id:m.id,
    			title:m.title,
    			content:m.content
    		}
    	}" 
    >
    	{{m.title}}
    router-link>
    
    
  • 第三步:读取参数

    this.$route.params.xxx
    

5.2 params注意事项

  1. 传递params参数时,必须提前占位,且要注意顺序与个数,但若用的是to的对象写法,那顺序无所谓了。

    注意:顺序不能乱、个数不能多、也不能少。可以用?控制必要性,默认是必须的

  2. 传递params参数时,若使用to的对象写法,必须使用name配置项,不能用path

    
    <router-link 
    	:to="{
    		name:'xiangqing',
    		params:{
               id:m.id,
               title:m.title,
               content:m.content
            }
    	}"
    >跳转router-link>
    
    
  3. 占位时,可以通过?可以控制params参数的必要性。

    {
      //含义:title三个参数可传、也可不传。
      path:'detail/:id/:title?/:content?', 
      component:Detail
    }
    
    
  4. 参数的值不能是对象,不能是空字符串、不能是数组。

6. 路由的props配置

  • 作用:让路由组件更方便的收到参数(可以将路由参数作为props传给组件)

    {
    	name:'xiangqing',
    	path:'detail/:id/:title/:content',
    	component:Detail,
    
      // props的对象写法,作用:把对象中的每一组key-value作为props传给Detail组件
      // props:{a:1,b:2,c:3}, 
    
      // props的布尔值写法,作用:把收到了每一组params参数,作为props传给Detail组件
      // props:true
      
      // props的函数写法,作用:把返回的对象中每一组key-value作为props传给Detail组件
      props($route){
        return $route.query
      }
    }
    
    

7. 缓存路由组件

  1. 作用:让不展示的路由组件保持挂载,不被销毁。

  2. 具体编码:

    
    <keep-alive :include="['News','Message']">
       <router-view>router-view>
    keep-alive>
    
    
    <keep-alive include="News">
       <router-view>router-view>
    keep-alive>
    
    
    <keep-alive exclude="News">
       <router-view>router-view>
    keep-alive>
    
    
    <keep-alive>
       <router-view>router-view>
    keep-alive>
    
    

8. replace 属性

  1. 作用:控制路由跳转时操作浏览器历史记录的模式。

  2. 浏览器的历史记录有两种写入方式:分别为pushreplace

    • push是追加历史记录(默认值)。
    • replace是替换当前记录。
  3. 如何开启replace模式:

    <router-link replace .......>Newsrouter-link>
    

9. 编程式导航

  1. 作用:不借助 实现路由跳转,让路由跳转更加灵活

    • 靠非click事件 或 靠一些逻辑触发跳转 —— 此时就需要编程式路由跳转
    • 最终呈现的元素不是a元素,此时就需要编程式路由跳转
    • 跳转:$router.push$router.replace
    • 前进:$router.forward
    • 后退:$router.back
  2. 具体编码:

    // $router的两个API
    this.$router.push({
      name:'xiangqing',
      params:{
        id:xxx,
        title:xxx
      }
    })
    
    // 备注:push和to属性的使用方式一样,也可以传递字符串,例如:this.$router.push('/about')
    this.$router.replace({
      name:'xiangqing',
      params:{
        id:xxx,
        title:xxx,
        content:xxxx
      }
    })
    
    

10. 处理编程式导航重复跳转报错

  1. 问题描述:编程式路由导航,若重复跳转会抛出: NavigationDuplicated 的错误。

  2. 问题原因:

    • vue-router 3.1.0 之后,编程式路由导航内部使用了Promise语法。
    • 如果路由跳转时没有指定:成功、失败回调函数,返回值就是Promise实例。
    • 且内部会判断路径否变化,规则如下:
      1. 无变化,则返回的Promise实例状态为失败
      2. 有变化,则返回的Promise实例状态为成功
  3. 解决办法:

    1. 办法一:指定成功 或 失败的回调函数(成功回调、失败回调同时都指定也可以),代码如下:

      this.$router.replace('/search',()=>{})
      
    2. 办法二:使用catch处理错误,代码如下:

      this.$router.replace('/search').catch(() => {})
      
    3. 办法三:见下面

11. 扩展_对原生方法进行增强

  1. 需求:对数组的push方法做增强,让push进去的数字,比写的数字大1

  2. 具体实现:

    //将Array原型上的push方法备份一份
    const originPush = Array.prototype.push
    
    //修改push方法为我们写的方法
    Array.prototype.push = function(value){
        value += 1
        return originPush.call(this,value)
    }
    
    

12. 对路由的push和replace进行增强

修改 VueRouter 原型上的pushreplace 方法 (推荐)

//将VueRouter原型上的push和replace保存一份
const originPush = VueRouter.prototype.push
const originReplace = VueRouter.prototype.replace 

//修改VueRouter原型上的push,用于解决重复跳转报错
VueRouter.prototype.push = function(location,onSuccess,onError){
    if(onSuccess || onError){
        return originPush.call(this,location,onSuccess,onError)
    }else{
        return originPush.call(this,location).catch(()=>{})
    }
}
//修改VueRouter原型上的replace,用于解决重复跳转报错
VueRouter.prototype.replace = function(location,onSuccess,onError){
    if(onSuccess || onError){
        return originReplace.call(this,location,onSuccess,onError)
    }else{
        return originReplace.call(this,location).catch(()=>{})
    }
}


//优化封装
function enhance (name,source){
  // 将VueRouter原型上原始的push保存一份
  const origin = source.prototype[name]
  // 修改VueRouter原型上的push
  source.prototype[name] = function(location,onSuccess,onError){
    if(onSuccess || onError){
      return origin.call(this,location,onSuccess,onError)
    }else{
      return origin.call(this,location).catch(()=>{})
    }
  }
}
enhance('push',VueRouter)
enhance('replace',VueRouter)

13. 路由的重定向

  1. 作用:将特定的路径,重新定向到已有路由。

  2. 具体编码:

    {
        path:'/',
        redirect:'/about'
    }
    
  3. 注意:

    • redirect要写完整。
    • path可以直接写其父级、或留空。
    • 子级路由若配置重定向,则其父级最好去掉name配置项,否则通过name跳转时,默认子路由不呈现。

14、注意传参事项:

路由跳转时当参数值为undefine时,会在路径上不显示参数

data() {
  return {
    keyword: "" || undefined,
  };
},
this.$router.push({
 path: "/search",
  query: {
    ...query,
    keyword: this.keyword,
  },
});

在这里插入图片描述

你可能感兴趣的:(Vue,vue.js)