route路由

概述

路由是通过对应url来渲染页面的一种方式,vue中主要的路由模式有俩种分别为 hash模式(默认的模式),history模式。

路由的分类及原理

hash路由

原理:通过对应的监听hash值变化来渲染不同的内容 (location.hash)

实现:通过onhashchange来监听对应的hash值的变化

window.onhashchange = ()=>{}

history路由

原理:通过监听对应的路径的变化来渲染不同的内容 (location.pathname)

实现:通过监听对应的onpopstate来处理对应的history.pushState和history.replaceState改变的路径

window.onpopstate = (){}

基础入门

导入vue的路由

  • cdn:<script src="./lib/vue-router.js"></script>
  • webpack构建的脚手架中进行node安装:npm i vue-router -S

构建路由对象几个步骤:

准备路由配置 (配置路由表routes),内有多个route 路由配置对象

let routes = [{
    //这个对象就是一个route
    name: 'hello ', //当前的路由的名字 唯一区分的
    path: '/hello', //当前路由的路径 可以不唯一
    component: hello //当前路由渲染的组件
}, {
    //这个对象就是一个route
    name: 'world ', //当前的路由的名字 唯一区分的
    path: '/world', //当前路由的路径 可以不唯一
    component: world //当前路由渲染的组件
}]

传入配置路由表(routes)构建路由对象(router)

let router = new VueRouter({
    mode: 'hash', //设置对应的路由采用的模式,默认为hash
    //routes: routes //这个地方属性名必须叫routes,可以简写为routes
    routes
})

将路由对象(router)传给vue实例

new Vue({
    el: "#app",
    data: {},
    // router: router
    router
})

路由显示设置

    <div id="app">
        <!-- 路由链接组件,router-link是内置组件-->
        <!-- 主要用于路由切换,它会被解析为a标签,to表示切换的地址 -->
        <router-link to="/hello">hello切换</router-link>
        <router-link to="/world">world切换</router-link>
        <!-- 路由视图组件,也是内置组件 -->
        <!-- 根据对应的路由自动渲染对应组件到链接router-link中 -->
        <router-view></router-view>
    </div>

route路由配置对象

route的属性

  • name :指定路由配置的名字(标识,唯一的)
  • path :指定路由配置的访问地址(访问路径唯一)
  • component :指定路由渲染的组件 components(指定渲染的组件集合)
  • redirect :重定向(访问当前的路由路径的时候,转换对应的路径访问)
  • children :子路由 (嵌套路由)
  • alias :别名
  • props :向组件传值
  • meta :相关配置(keepAlive:true是否缓存;auth:"user" ,具备什么权限;isAuth:true需要鉴权)
    let admin = {
            template: `
                <div>admin内的页面切换:
                    <router-view></router-view>
                    {{name}}{{$route.meta.keepAlive}}
                </div>`,
            props: ['name']
        }
        //配置对象
        let routes = [{
            name: 'admin',
            path: '/admin',
            component: admin,
            alias: 'father', //别名
            //向组件传值
            props() {
                return {
                    name: '你好'
                }
            },
            //相关配置
            meta: {
                keepAlive: true, //是否缓存
                auth: "user", //具备什么权限
                isAuth: true //需要鉴权
            },
            //嵌套路由配置,子页面的路径不能加/
            children: [{
                name: 'adminUser',
                path: 'user',
                component: {
                    template: '<div>管理用户页</div>'
                }
            }, {
                name: 'adminList',
                path: 'list',
                component: {
                    template: '<div>管理列表页</div>'
                }
            }]
        }]
        //传入规则构建路由对象
        let router = new VueRouter({
            mode: 'hash', //设置对应的路由采用的模式,默认为hash
            //routes: routes //这个地方属性名必须叫routes,可以简写为routes
            routes
        })
        new Vue({
            el: "#app",
            data: {},
            // router: router
            router
        })

通过$route来获取配置对象

页面中访问:{{$route.meta.keepAlive}}

方法中访问:this.$route.meta.keepAlive

router-link

router-link路由链接组件,它是一个全局内置组件,用于路由的切换,会被解析为a标签,to表示切换的地址

router-link的相关属性

  • to属性 :用于跳转对应的路径

  • tag属性 :显示什么标签(默认显示a标签)

  • replace属性 :采用替换的形式没有历史页面, push属性:添加形式是默认的,有历史页面

  • exact 精准:默认的匹配模式为模糊匹配,加上exact为精准匹配

  • 样式名:router-link-active 匹配激活的样式、router-link-exact-active 精确匹配的样式 (路径名必须全部一致)

     <style>
        a {text-decoration: none;}
        .router-link-active {background-color: palevioletred}
        .router-link-exact-active {background-color: yellowgreen;}
    </style>
    <div id="app">
        <!-- 基础使用 -->
        <router-link to="/user">son</router-link><br>
        <!-- 属性绑定使用 -->
        <router-link :to="{name:'son'}">属性绑定son</router-link><br>
        <router-link :to="{path:'/shop'}">属性绑定daughter</router-link><br>
        <!-- tag属性 -->
        <router-link to="/user" tag="button">tag属性</router-link><br>
        <!-- repalce属性和push属性 -->
        <router-link to="/user" replace>replace</router-link><br>
        <!-- 精准exact -->
        <router-link to="/shop" exact>exact</router-link><br>
        <router-view></router-view>
    </div>

【补充】

属性指定样式名:

  • exact-active-class
  • active-class

新增的自定义custom(boolean类型值)

router-view

router-view路由视图组件,它是一个全局内置组件,根据对应的路由自动渲染

router-view中的属性 

  • name属性:用于指定切换路由下对应的组件进行显示
  • route解析进行懒加载

<!-- name指定渲染的组件 -->
<router-view name="com"></router-view>

VueRouter构造

相关传入的option属性:

  • routes属性传入对应的路由表(它是一个数组)
  • mode属性 指定路由的模式 (字符串)

mode属性的取值:

  • hash
  • history
  • abstract (用于原生app的开发 完全不依赖于浏览器)

【注意事项】

vue的版本和vue-router得协调,vue2用到vue-router为3,vue3用于vue-router版本为4

编程式导航

概述:利用代码进行路由的切换

主要使用的是路由对象的方法

  • push 会新增历史页面
  • replace 不会新增历史页面
  • 它们都支持传入path路由字符串或对象,可以使用path来指定路径名,也可以使用name来指定路由配置名
    <div id="app">
        <!-- 编程式导航:通过函数方法切换、使用this.$router. -->
        <button @click="handlerByPath('/first')">上一个</button>
        <button @click="handlerByName('last')">下一个</button>
        <!-- 直接切换:使用$router. -->
        <button @click="$router.push({path:'/first'})">上一个</button>
        <button @click="$router.replace({path:'/last'})">下一个</button>
        <button @click="$router.replace({name:'last'})">下一个</button>
        <router-view></router-view>
    </div>
    <script src="https://unpkg.com/vue@2.7.14/dist/vue.js"></script>
    <script src="./lib/vue-router.js"></script>
    <script>
        let first = {template: `<div>上一个</div>`}
        let last = {template: `<div>下一个</div>`}
        let routes = [{
            name: 'first',
            path: '/first',
            component: first
        }, {
            name: 'last',
            path: '/last',
            component: last
        }]
        let router = new VueRouter({routes})
        new Vue({
            el: "#app",
            data: {},
            router,
            methods: {
                handlerByPath(path) {
                    this.$router.push({ // path: path或
                        path})},
                handlerByName(name) {
                    this.$router.replace(name)}
            }
        })
    </script>

keepAlive

keepAlive是一个内置组件,它提供了缓存的作用。

keepAlive简单使用

在路由配置表routes中添加: meta: {keepAlive: true }

        let routes = [{
            name: 'first',
            path: '/first',
            component: first,
            meta: {keepAlive: true }
        }, {
            name: 'con',
            path: '/con',
            component: con,
            meta: {keepAlive: false }
        }, {
            name: 'last',
            path: '/last',
            component: last,
            meta: {keepAlive: false }
        }]

在路由视图组件使用 keepAlive 将 router-view 包起来

     <div id="app">
        <router-link to="/first">first</router-link>
        <router-link to="/con">con</router-link>
        <router-link to="/last">last</router-link>
        <!-- 会缓存所有的组件 -->
        <keep-alive>
            <router-view></router-view>
        </keep-alive>
        <!-- 缓存指定组件,使用include="组件名",缓存多个使用:include="['组件名1','组件名2']"-->
        <keep-alive include="tom">
            <router-view></router-view>
        </keep-alive>
        <!-- 使用meta的keepAlive判断是否缓存 -->
        <keep-alive>
            <router-view v-if="$route.meta.keepAlive"></router-view>
        </keep-alive>
        <!-- 其他组件不显示 -->
        <router-view v-if="!$route.meta.keepAlive"></router-view>
    </div>

keepAlive新增的生命周期钩子函数

  • activated 激活状态
  • deactivated 未激活
        let first = {
            template: `<div></div>`,
            activated() {console.log('激活了first');},
            deactivated() {console.log("不激活first");},
        }

keepAlive的属性

  • include 需要被缓存的组件
  • exclude 不需要被缓存的组件
  • 它们支持字符串、传入正则、传入数组

路由传参

它有俩种传递的方式,分为 query 和 params。

query传参

主要是利用对应的 ? 拼接进行传参

<div id="app">
    <!-- 多种传参方式 -->
    <!-- 普通传参 -->
    <router-link to="/user?name=tom&age=15">普通传参</router-link>
    <!-- 绑定to -->
    <router-link :to="{name:'last',query:{name:'marry',age:11}}">绑定to和name传参</router-link>
    <router-link :to="{path:'/shop',query:{name:'tonny',age:11}}">绑定to和path传参</router-link>
    <!-- 编程式导航传参 -->
    <!-- 编程式导航传参,普通方式 -->
    <button @click="$router.push('/user?name=tilavine&age=15')">编程式导航传参1</button>
    <!-- 编程式导航传参,path传参 -->
    <button @click="$router.push({path:'/shop',query:{name:'selena',age:11}})">编程式导航传参2</button>
    <!-- 编程式导航传参,name传参 -->
    <button @click="$router.push({name:'last',query:{name:'rose',age:11}})">编程式导航传参3</button>
    <router-view></router-view>
</div>
<script src="https://unpkg.com/vue@2.7.14/dist/vue.js"></script>
<script src="./lib/vue-router.js"></script>
<script>
    let first = {
        template: `<div>第一个组件:{{$route.query.name}}{{$route.query.age}}</div>`,
        created() {console.log(this.$route.query); }
    }
    let last = {
        template: `<div>第二个组件:{{name}}{{age}}</div>`,
         props: {
             name: {
                default: '默认值',
                type: String
             },
             age: {
                default: 0,
                type: Number
             }
         }
    }
    let routes = [{
         name: 'first',
         path: '/user',
         component: first
    }, {
         name: 'last',
         path: '/shop',
         component: last,
         props($route) {
             return {
                name: $route.query.name,
                age: Number($route.query.age)
             }
         }
    }]
    let router = new VueRouter({
        routes
    })
    new Vue({
        el: "#app",
        data: {},
        router
    })
</script>

params传参

利用path路由传参,它的数据是使用 / 后面携带的

注意:如果是绑定to且使用params:{参数}的对象形式传递参数传递,那么不能使用path传递,建议使用name

    <div id="app">
        <!-- 普通传递 -->
        <router-link to="/1">普通传递</router-link>
        <!-- 绑定to使用name传递 -->
        <router-link :to="{name:'first',params:{id:2}}">name传递</router-link>
        <!-- 编程式导航传递 -->
        <button @click="$router.push('/3')">编程式导航传递1</button>
        <router-view></router-view>
    </div>
    <script src="https://unpkg.com/vue@2.7.14/dist/vue.js"></script>
    <script src="./lib/vue-router.js"></script>
    <script>
        let first = {
            // template: `<div>{{$route.params.id}}</div>`,
            template: `<div>{{id}}</div>`,
            props: {
                id: {
                    default: 0,
                    // type: Number
                }
            }
        }
        let routes = [{
            name: "first",
            path: "/:id",
            component: first,
            props($route) {
                return {id: $route.params.id}
            }
        }]
        let router = new VueRouter({
            routes
        });
        new Vue({
            el: "#app",
            data: {},
            router
        })
    </script>

query传参和params传参的区别

  • query传参是使用?拼接的形式传递,params传参是通过 / 路径的拼接
  • query传参可以指定path来传递也可以指定name,params传参必须指定name来传递
  • query传参不会产生丢失问题因为它会缓存数据,params不会缓存,所有页面重新编译的时候,会产生数据丢失的问题
  • 要解决对应的params传参丢失的问题,要指定对应的path路径,通过:名字来规范对应的接收的数据的key

路由守卫

主要负责监听路由的进入及相关操作,守卫路由的入口。

路由守卫分类

  • 全局路由守卫 (Router对象)
  • 独享路由守卫 (route配置的)
  • 组件路由守卫 (组件的)

全局路由守卫

相关函数:

  • beforeEach 进入之前
  • beforeResolve 进入成功之前
  • afterEach 进入以后
         let routes = [{
            name: 'first',
            path: '/user',
            component: first,
            meta: {isAuth: true}
        }, {
            name: 'last',
            path: '/shop',
            component: last,
            meta: {isAuth: false}
        }]
        let router = new VueRouter({routes})
        //to 到达的路由配置对象 from 来的路由配置对象 next下一个(放行 方法)
        //进入之前 验证对应的权限
        router.beforeEach((to, from, next) => {
            //是否需要鉴权
            if (to.meta.isAuth) {
                //携带token去请求查看是否具备权限
                let auto = JSON.parse(localStorage.getItem('token')).auth
                if (auto == 'root1') {
                    //放行
                    next()
                } else {next('/shop')}
            } else {next()}
        });
        //进入成功
        router.beforeResolve((to, from, next) => {next()});
        //进入之后
        router.afterEach((to, from) => {});

独享路由守卫

主要拦截对应的路由配置下的组件

相关函数:

  • beforeEnter 进入之前
     let routes = [{
            //path 路径 name 名字 component 组件
            name: 'first',
            path: '/user',
            component: first,
            meta: {isAuth: true},
            //进入之前
            beforeEnter: (to, from, next) => {
                 // 是否需要鉴权
                if (to.meta.isAuth) {
                   //携带token去请求查看是否具备权限
                    let auto = JSON.parse(localStorage.getItem('token')).auth
                    if (auto == 'root1') {
                        //放行
                        next()
                    } else { next('/shop') }
                } else {next() }
            }
        }, {
            name: 'last',
            path: '/shop',
            component: last,
            meta: {isAuth: false}
        }]

组件路由守卫

主要拦截对应的组件

生命周期钩子:

  • beforeRouteEnter 进入之前
  • beforeRouteLeave 离开之前
        let first = {
            template: `<div>拦截</div>`,
            beforeRouteEnter(to, from, next) {
                //是否需要鉴权
                if (to.meta.isAuth) {
                    //携带token去请求查看是否具备权限
                    let auto = JSON.parse(localStorage.getItem('token')).auth
                    if (auto == 'root') {
                        //放行
                        next()
                    } else {next('/shop')}
                } else {next()}
            },
            //进入之后才会触发
            beforeRouteLeave(to, from, next) {
                if (confirm('当前是否离开')) {next()}
            }
        }

【补充】

动态路由

根据params传参来进行相关操作

路由的添加及属性方法

addRoutes 添加路由表 ***

  • 添加路由表,传入是数组
  • router.addRoutes(routes)

currentRoute 获取当前路由配置对象

  • router.currentRoute

go 去对应的路由页面 (和history.go一致)

  • router.go() //去任何页面
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值