• Vue Router学习


    1、什么是路由?

    根据用户给出的url地址,导航到不同组件中;

    2、vue router实现原理

    SPA:单一页面应用程序,只有一个完整的页面,它在加载页面时,不会加载整个界面,而是只更新某个指定的容器中的内容。单页面应用(SPA)的核心之一是:更新视图而不是更新请求页面。Vue Router在实现单页面前端路由时,提供了两种方式:hash模式和history模式,默认使用的是hash模式。

    2.1、hash模式

    • url hash就是类似于:localhost:8080/#/login

    这种#后面hsah值的变化,并不会导致浏览器向服务器发出请求,浏览器不发出请求,也就不会刷新页面。而每次hash值的变化,还会触发hashchange事件,通过这个时间我们就可以知道hash值发生了哪些变化。我们便可以监听hashchange来实现更新页面部分的内容的操作。因此改变hash不会重新加载页面

        function matchAndUpdate(){
          
    	}
    window.addEventListener("hashchange",matchAndUpdate)
    
    • 1
    • 2
    • 3
    • 4

    2.2、history模式

    因为HTML5标准发布,多了两个API, pushState 和replaceState,通过这两个API可以改变url地址且不会发送请求。同时还有popstate事件。通过这些就能用另一种方式来实现前端路由了,但原理都是跟hash实现相同的。用了HTML5的实现,单页路由的url就不会多出一个#,变得更加美观。但因为没有#号,所以当用户刷新页面之类的操作时,浏览器还是会给服务器发送请求。为了避免出现这种情况,所以这个实现需要服务器的支持,需要把所有路由都重定向到根页面。

        function matchAndUpdate(){
          
    	}
    window.addEventListener("popstate",matchAndUpdate)
    
    • 1
    • 2
    • 3
    • 4

    3、路由基础

    3.1、路由列表

    const router = new VueRouter({
    	路由列表:是一个数组
        routes:[
        	单个路由
        	path:表示路由路径字符串,在path中需要/开头,目的使全局路由对象能够监听到某个用户请求的路径;
        	component:组件,如果path与用户访问的路径匹配,则去查找相应的组件,让组件渲染页面
    
    		{
    		path:/login,
    		component:Login
    		}
    	]
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    3.2、路由标签

    <router-link>标签,进行路由导航,它会被Vue解析为一个超链接;
    to属性:配置路由路径;
    <router-link to="/login">登录</router-link>(声明式导航)
    
    通过router-link标签导航之后,组件如何渲染到页面中?
    <router-view/>:渲染某个路由路径对应的组件,称为路由出口
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    4、动态路由匹配

    我们经常需要把某种模式匹配到的所有路由,全都映射到同个组件。例如,我们有一个User组件,对于所有ID各不相同的用户,都要使用这个组件来渲染。那么,我们可以在vue-router的路由路径中使用动态路径参数”来达到这个效果:当我们在地址后面直接添加任意字符,我们会发现文档内容随着我们的更改而改变。

    4.1、动态路由路径

    {
    	path:/user/:id,//通过$route.params.id可以获取到这个值,如果使用path:/user-* 通配符,是无法获取的
    	component:Login
    }
    
    <router-link to="/user/1001">登录</router-link>
    <router-link to="/user/1002">登录</router-link>
    
    
    //传递多个参数
    {
    	path:/user/:id/:uerName,//通过$route.params.id可以获取到这个值,如果使用path:/user-* 通配符,是无法获取的
    	component:Login
    }
    
    this.$router.push(`/user/${id}/${name}`)
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    4.2、响应(监听)动态路由参数的变化

     //侦听器:侦听当前路由的变化
      watch: {
        //to:导航之后(跳转之后)的路由对象
        //from:旧值,跳转前的路由对象
        "$route":(to, from)=> {
          console.log("导航之后",to);
          console.log("前",from);
        }
      },
      
    官网上是这样写的
      created() {
        //侦听器:侦听当前路由的变化
        this.$watch(() => this.$route.params,
            (toParams, previousParams) => {
              // 对路由变化做出响应...
              console.log(toParams);
              console.log(previousParams);
            })
      },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    4.3、捕获所有路径(路由)

    路由路径通配符*。
    路由列表的匹配模式是自上而下的逐个路由匹配,带有通配符的路由一定放在路由列表最后。

    {
            path: "/*",
            component: Error
        }
    
    • 1
    • 2
    • 3
    • 4

    5、嵌套路由

    {
            path: '/about',
            component:About,
            children: [{
                //嵌套路由列表
                // path:"list",//相对路径是上级路由作为前缀路径 to="/about/list"
                path:"/list",//绝对路径不能以上级路由作为前缀路径 to="/list"
                component:Child
            }]
        },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    6、编程式导航

    6.1、push

    //字符串形式
    this.$router.push('/vuex');
    //对象形式
    this.$router.push({path:'/vuex'})
    
    • 1
    • 2
    • 3
    • 4

    路由在导航之后会形成历史记录history;
    push:在历史列表中追加一个

    6.2、replace

    replace:在历史列表中替换上一个记录,不可以后退到上一个页面;

    在声明式导航中的应用:

    <router-link to="xxxx" replace>xxx</router-link>
    
    • 1

    编程式导航:

    this.$router.replace('/vuex')
    
    • 1

    一般可以用在登录后,跳转到主页,就用replace,防止用户回退时回退到登录页面。

    6.3、go

    历史前进或后退多少步;

    this.$router.go(-3)
    
    • 1

    7、路由配置

    7.1、命名路由

    为每个路由的配置添加一个name属性,且必须唯一;

    {
            path: "/login",
            name:"login",//路由名称
            component: Login
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    根据路由名称进行导航

    //声明式
    <router-link :to="{name:'vuex'}" replace>xxx</router-link>
    
    //编程式导航(对象形式,不能是字符串形式)
    this.$router.push({name:'vuex'})
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    7.2、重定向redirect

    通过重定向redirect是实现组件的复用;

    	{
            path: "/",
            redirect:"/home",
            //redirect: {name: "vuex"}也可以通过组件名称进行重定向
        },
        {
            path: '/home',
            name: 'home',
            component: HomeView
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    7.3、别名alias

    {
            path: '/home',
            name: 'home',
            component: HomeView,
            alias:"/hm"//路由别名
        },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    7.7、其他

    export default new Router({
        mode: 'history', //路由模式,取值为history与hash
        base: '/', //打包路径,默认为/,可以修改
        routes: [
        {
            path: string, //路径
            ccomponent: Component; //页面组件
            name: string; // 命名路由-路由名称
            components: { [name: string]: Component }; // 命名视图组件
            redirect: string | Location | Function; // 重定向
            props: boolean | string | Function; // 路由组件传递参数
            alias: string | Array<string>; // 路由别名
            children: Array<RouteConfig>; // 嵌套子路由
            // 路由单独钩子
            beforeEnter?: (to: Route, from: Route, next: Function) => void; 
            meta: any; // 自定义标签属性,比如:是否需要登录
            icon: any; // 图标
            // 2.6.0+
            caseSensitive: boolean; // 匹配规则是否大小写敏感?(默认值:false)
            pathToRegexpOptions: Object; // 编译正则的选项
        }
        ]
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    8、路由传参

    两个组件之间的数据传递;

    8.1、query

    1. 字符串拼接形式
    <router-link to="/VModel?name=user&pwd=123"></router-link>
    
    //接收参数
    this.$route.query
    
    • 1
    • 2
    • 3
    • 4

    在这里插入图片描述

    1. 以对象的形式
    //传递的是一个对象,也可以拼接为字符串形式
    this.$router.push({path:'/vuex',query:{name:'111',age:18}})
    
    //接收参数
    this.$route.query
    
    • 1
    • 2
    • 3
    • 4
    • 5

    8.2、params

    1. 动态路由匹配传递参数(路径传参)
      这种方式必须传参
     {
            path: '/vuex/:ids/:name',
            name: 'vuex',
            component: VueXStudy,
        }
    
    <router-link to="/vuex/1/xiao">xxxx</router-link>
    
    
    //接收参数
    this.$route.params
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    在这里插入图片描述

    1. 编程式导航传参
    • 参数隐藏,不在路径中出现
    • 路径固定
    • 必须通过name导航
    this.$router.push({name:'vuex',params:{name:'张三',age:18}})
    
    //接收参数
    this.$route.params
    
    • 1
    • 2
    • 3
    • 4

    在这里插入图片描述

    1. 声明式导航传参
    <router-link :to="{name:'vuex',params:{name:'李四'}}">xxxx</router-link>
    
    //接收参数
    this.$route.params
    
    • 1
    • 2
    • 3
    • 4

    8.3、props

    在组件中使用$route会使之与其对应路由形成高度耦合,从而使组件只能在某些特定的url使用,限制了其灵活性。

    解耦

    {
            //路由路径中的占位符名称必须与组件props变量名称一致
            
            path: '/vuex/:id/:userName',
            name: 'vuex',
            component:VueXStudy,
            //在路径配置中开启props传参
            props: true
        }
        
    <router-link to="/vuex/1001/王麻子">xxxx</router-link>
    
    //定义props对象接收路由参数
    props:{
        id:String,
        userName:String
      }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    8.4、query 和 params的区别

    1. query 可以使用path和name,params只能使用name
    2. query传参刷新后可以保存,params不会保存;
    3. query传递的参数会显示在url地址中,params不会显示;
    4. 通过字符串拼接的形式传递参数,使用的是$route.query接收参数;
    5. query不可以和动态路由匹配一起使用,而使用params接收参数

    9、导航守卫

    “导航”表示路由正在发生变化;
    类似于javaweb里面的过滤器,拦截器

    9.1、全局前置守卫

    router.beforeEach()一般用来做一些进入页面的限制。比如没有登录,就不能进入某些页面,只有登录了之后才有权限查看某些页面。说白了就是路由跳转前根据业务逻辑判断是否拦截。

    router.beforeEach(回调函数),回调函数中的三个参数

    1. to:将要导航到的路由对象
    2. from:导航之前的路由对象
    3. next:导航函数,在函数执行时,此函数必须执行一次,且仅能执行一次
    next():无参数调用就是对导航的放行;
    next(阻止导航,阻止导航后跳转的路径):阻止导航,阻止路由跳转
    
    //有参数时编写的形式:
    next( '/login')
    next({path: '/login'})
    next({name: 'login'})
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    //前置守卫
    //模拟身份认证:判断用户是否登录,如果没有登录,跳转至登录页面
    router.beforeEach((to, from, next) => {//路由跳转中
        if (to.path == "/") {//"/"默认进入登录页面
            next();
        } else {
            if (sessionStorage.getItem("userInfo")) {
                next()
            } else {
                next({path: '/'})
            }
        }
    })
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    9.2、路由独享守卫

    守卫范围:当前路由以及当前路由下的所有嵌套路由;

    {
            path: '/vuex',
            name: 'vuex',
            component: () => import( '../components/vuex/VueXStudy.vue'),
            beforeEnter: (to, from, next) => {
                console.log("to", to);
                console.log("from", from);
                next();
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    10、路由懒加载

    未使用懒加载

    import Vue from 'vue'
    import VueRouter from 'vue-router'
    import HomeView from '../views/HomeView.vue'
    
    Vue.use(VueRouter)
    export default new VueRouter({
        routes:[
    		{
            path: '/home',
            name: 'home',
            component: HomeView,
       		}
    	]
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    10.1、vue异步组件实现懒加载

    方法如下:component:resolve=>(require(['需要加载的路由的地址']),resolve)

    import Vue from 'vue'
    import VueRouter from 'vue-router'
    
    Vue.use(VueRouter)
    export default new VueRouter({
        routes:[
    		{
            path: '/home',
            name: 'home',
            component: resolve=>(require(["../views/HomeView.vue"],resolve)),
       		}
    	]
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    10.2、ES6 提出的import方法(最常用,推荐使用)

    方法如下: component: () =>import('需要加载的模块地址')

    import Vue from 'vue'
    import VueRouter from 'vue-router'
    
    Vue.use(VueRouter)
    export default new VueRouter({
        routes:[
    		{
            path: '/home',
            name: 'home',
            component: () => import( '../views/HomeView.vue')
       		}
    	]
    })
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    10.3、webpack提供的require.ensure()实现懒加载

    1. vue-router配置路由,使用webpack的require.ensure技术,也可以实现按需加载。
    2. 这种情况下,多个路由指定相同的chunkName,会合并打包成一个js文件
    3. require.ensure可实现按需加载资源,包括js,css等。他会给里面require的文件单独打包,不会和主文件打包在一起。
    4. 第一个参数是数组,表明第二个参数里需要依赖的模块,这些会提前加载。
    5. 第二个是回调函数,在这个回调函数里面require的文件会被单独打包成一个chunk,不会和主文件打包在一起,这样就生成了两个chunk,第一次加载时只加载主文件。
    6. 第三个参数是错误回调。
    7. 第四个参数是单独打包的chunk的文件名

    11、vue2中动态添加路由router.addRoute

    动态添加根路由:router.addRoute({path:xxx,name:xx....})
    动态添加子路由:router.addRoute(parentName,{path:xxx,name:xx....}),其中parentName为父级路由定义的name字段。

  • 相关阅读:
    使用git将本地项目推送到远程仓库github
    算法训练营第四十三天(9.5)| 动态规划Part16:距离
    iTOP-RK33399开发板Qt系统移植-交叉编译Qt代码
    C++项目实战-UDP服务器
    docker-compose模板文件、命令的使用
    uniapp使用scroll-view,设置横向,内容重叠的问题解决
    CH455G驱动数码管
    【RuoYi-Vue-Plus】学习笔记 36 - Redisson(十)发布 | 订阅功能分析(Redisson 源码)
    【Go-Lua】Golang嵌入Lua代码——gopher-lua
    LiveGBS流媒体平台GB/T28181功能-国标设备通道分享手机PC浏览器观看直播
  • 原文地址:https://blog.csdn.net/fangqi20170515/article/details/126772002