Vue路由router/导航守卫

Vue路由

用的前端路由系统,通过改变URL,在不重新请求页面的情况下,更新页面视图。
利用URL中的hash(“#”);

vue 中路由的跳转方式:

        1. 声明式路由 : 通过 router-link 标签实现的
        2. 编程式路由 : 通过 路由对象的方法  $router.push() 方法实现的

路由加前缀

new Router({
  mode: 'history', // 访问路径不带#号
  base: '/page/aa',  // 配置单页应用的基路径
});

页面这样访问 http://localhost:8080/page/aa/ 和 http://localhost:8080/ 访问的效果是一样的。

声明式路由

<style>
    .router-link-exact-active {
        color: red;
        /* 渲染的属性 */
    }
</style>

<body>
    <div id="app">
        <!-- 使用 router-link 组件来导航. -->
        <!-- 通过传入 `to` 属性指定链接. -->
        <!-- <router-link> 默认会被渲染成一个 `<a>` 标签 -->
        <p>
            <router-link to='/'>首页</router-link>
            <!--router-link-active :当前激活的路由          因为/,其它路由也有/, 所以会一直被激活  -->
            <router-link to='/main'>主体</router-link>
            <router-link to='/login'>登录</router-link>
        </p>
        <!-- 5 router-view标签是vue提供的内置标签,专门用来渲染 路由 -->
        <!-- 路由出口 -->
        <!-- 路由匹配到的组件将渲染在这里 -->
        <router-view></router-view>
    </div>
</body>
<script src="./js/vue.js"></script>
<script src="./js/vue-router.js"></script>
<script>
    // 1.  创建路由页面模板 本质就是组件
    const main = {
        template: `<div>这是主体页面</div>`
    }
    const login = {
        template: `<div>这是登录页面</div>`
    }
    const index = {
            template: `<div>这是首页默认路由</div>`
        }
        // 2.   创建路由的配置项
    const routes = [{
            path: '/', // 路径匹配的路由
            component: index
        }, {
            path: '/main', // 路径  匹配的路由
            //  路由级页面组件   component注册组件
            component: main
        }, {
            path: '/login',
            component: login
        }]
        //  3. 生成路由的实例对象
    const router = new VueRouter({
            routes // (缩写) 相当于 routes: routes
        })
        //  4. 把路由对象注册到vue 实例中
    const app = new Vue({
        el: "#app",
        //  路由的配置项
        // 记得要通过 router 配置参数注入路由,
        // 从而让整个应用都有路由功能
        router
    })
</script>

在这里插入图片描述
router-link 的 tag 属性 可以指定渲染的标签 tag属性值是标签名
指定类名: 给router-link标签添加 属性指定类名

  active-class: 默认值         router-link-active(激活)
  exact-active-class: 默认值   router-link-exact-active(渲染)

例子

<router-link to='/' tag='p' active-class='active' exact-active-class='current'>首页</router-link>

编程式路由

路由传参:
1. 通过query实现 : query 传参 和 path 结合使用
2. 通过params实现 : parmas 传参 和 name 结合使用 (name 就是命名路由的一个属性, 通过name属性命名路由)
3. path 结合 params 使用, 则params会被忽略

query结合path传参结合使用方式通过 query 传递参数 : query 是一个对象; 传递的参数会拼接在路径上url

  <div id="app">
        <!-- <router-link to='/list'>列表</router-link>
        <router-link to='/order'>订单</router-link>   这是  声明式路由的写法-->

        <!-- 编程式路由的写法 -->
        <!--(1) 通过query实现 传参 -->
        <button @click='list'>列表</button>
        <router-view></router-view>
    </div>
    <script src="./js/vue.js"></script>
    <script src="./js/vue-router.js"></script>

    <script>
        const List = {
            template: `
                <div>
                    hello  列表
                </div>
            `
        }
        const routes = [{
            path: '/list',
            component: List
        }]
        const router = new VueRouter({
            routes
        })
        const app = new Vue({
            el: '#app',
            router,
            methods: {
                list() {
                    // (1)编程式路由: 通过 路由对象$router  的 push() 进行跳转
                    //this.$router.push('list') //这样写是跳转 参数是一个字符串类型的path 
                    // (1) 跳转和传参   参数是一个对象 可以进行路由传参
                    this.$router.push({
                        path: '/list',
                        //  通过query进行传参 第一个种传参形式通过 query, 参数会拼接在路径的后边 , 类似于get请求
                        //query 传参 页面刷新 参数不会丢失
                        query: {
                            tab: 'share',
                            id: 100
                        },
                        // 如果 使用了path 进行路由跳转,添加params 则会被忽略
                        // params: {
                        //     id: 100
                        // }
                    })
                }
            }
        })
    </script>
</body>

上面是在编程式路由中传参
声明式路由传参
也可以在<router-link : to=>中传参

这时的to前面要加v-bind,来告诉vue这是一个对象

 <router-link :to='{
            path:"/order", 
            query:{
                id:100,
              tab: "share",
            }
            }'>订单</router-link>

在这里插入图片描述

params结合name传参使用方式 params 也是一个对象 ; 传递的参数是不会显示在路径URL 上

<div id="app">
    <!-- <router-link to='/list'>列表</router-link>
    <router-link to='/order'>订单</router-link> 声明式路由 -->
    //编程式路由
    <button @click='order'>订单</button>

    <router-view></router-view>
</div>
<script src="./js/vue.js"></script>
<script src="./js/vue-router.js"></script>

<script>
    const Order = {
        template: `
            <div>
                order 页面
            </div>
        `
    }
    const routes = [{
        path: '/order',
        //  name 命名路由,可以给路由起别名
        name: 'Order',
        component: Order
    }]
    const router = new VueRouter({
        routes
    })
    const app = new Vue({
        el: '#app',
        router,
        methods: {
            order() {
                //(2)编程式路由: 通过 路由对象$router 的 push() 进行跳转
                // this.$router.push('order')
                //(2)传参和跳转  路由传参的方式:通过 params 传参,需要结合命名路由实现
                // params 传参 页面刷新,参数就会自动丢失  !!
                this.$router.push({
                    name: 'Order', //这个name名与路由途径routes中name名对应
                    params: {
                        type: '衣服'
                    }
                    //  query 可以 和name结合使用,但是不建议(使用后刷新参数不丢失)
                    // query: {
                    //     id: 200
                    // }
                })

            }
        }
    })
</script>

在这里插入图片描述

对比
在这里插入图片描述

 路由传参:
            1. query 传参  : {path:'/zoom', query:{}}
            2. params 传参  : {name:'zoom', params:{}}

动态路由

动态路由渲染的是同一个模板

 获取声明式动态路由的参数:
            组件模板中: $route.params.id
            方法中: this.$route.parmas.id 

获取编程式动态路由的参数:

            1. 获取query参数: 
                组件模板中获取: $route.query.key
                方法中(组件中): this.$route.query.key

            2. 获取params参数:
                组件模板中获取: $route.params.key
                方法中(组件中): this.$route.parmas.key

vuecli实例

<!--组件中使用 <p>传过来的=>:{{ $route.params.type }}</p> -->
 <p>传过来的=>{{ listID }}</p>

----
computed: {//计算属性
    listID() {
      // params是参数的意思
      return this.$route.params.type;
    },
  },

区分两个对象:

  $route :  代表的是当前路由信息对象 (就是url地址的实时参数)
  $router : 代表的是路由实例对象

vue路由的通配符

vue路由的通配符

 path:'*',//匹配任意路径
例如  path:"/box*"

这个时候跳转的路径里只要含有 box 就可以跳转
可以是/box1或/box&token=123

例如  	path: '/box/:id(\\d+)',

只要/box/2 后面是数字就跳转

Route 匹配官网

watch监听路由

方法一:
watch:{
  $router(to,from){
       console.log(to.path)
  }
}
方法二:
watch: {
   $route: {
     handler:  function (val, oldVal){
       console.log(val);
     },
     // 深度观察监听
     deep:  true
   }
},
方法三:
watch: {
   '$route' : 'getPath'
},
methods: {
   getPath(){
     console.log( this .$route.path);
   }
}

侦听路由详细

监听的是data中的数据的改变, 监听的是 handler(newValue, oldValue)
监听的是路由的改变:监听的是 handler(to, from)  从哪个路由 跳转到哪个路由 (从哪来到哪去)

fullPath和path区别

fullPath匹配路由,path匹配路径。

例如:

路由是:/path/one
真正路径是:/path/true

那么此时path为/path/true,而fullPath为/path/one

router对象的方法

和BOM: history 对象 类似

        router.replace() : 替换当前路由, 该路由不会添加到历史记录中
        router.go(n) : 前进/后退 路由跳转  n:整数, 正值代表前进, 负值后退 
        router.back() : 后退
        router.forward() : 前进

嵌套路由和重定向(redirect)

vue 路由: 存在子由路(嵌套路由) 通过 children 属性定义嵌套路由

使用嵌套路由时。 父路由和子路由的路径会自动进行拼接, 得到最后的路由 /parent/child
所以子路由的路径匹配不用写斜杠/

 const routes = [
        {
            path:path,
            component:parentname,
            // children 就是子由路
            children:[
                {
                    path:path,
                    component:childname
                },{
                     path:path,
                    component:childname
                }
            ]
        }
    ]

例:

const routes = [
  {
    path: '/',
    name: 'Home',
    component: Home,
    redirect: '/about',当访问/时。重定向到/about
  },
  {
    path: '/about',
    name: 'about',
    component: () => import('../views/About.vue')
  }
]
<body>
    <div id="app">
        <router-link to='/index'>首页</router-link>
        <router-link to='/order'>订单</router-link>
        <router-view></router-view>
        <!-- 出口 -->
    </div>
</body>
<script src="./js/vue.js"></script>
<script src="./js/vue-router.js"></script>
<script>
    const index = {
        template: `
        <div>
            <p>这是首页</p>
            <router-link to='/list'>二级页面</router-link>
            <router-view></router-view>
        </div>
        `
            //二级页面和出口
    }
    const order = {
        template: `
        <div>
            <p>这是订单</p>
        </div>
        `
    }
    const list = { //二级页面的模板
        template: `
                <div> <strong>这是商品列表页 </strong></div>
             `
    }
    const routes = [{
        path: '/',
        //页面重定向
        redirect: '/index'
            //要不然component: index再写一次
    }, {
        path: '/index',
        component: index,
        children: [{
            path: '/list',
            component: list
        }]
    }, {
        path: '/order',
        component: order
    }]
    const router = new VueRouter({
        routes
    })
    const app = new Vue({
        el: "#app",
        router
    })
</script>

导航守卫

导航守卫就是路由跳转过程中的一些钩子函数
组件内守卫和组件钩子函数不冲突

官方解释:

“导航”表示路由正在发生改变。正如其名,vue-router提供的导航守卫主要用来通过跳转或取消的方式守卫导航。有多种机会植入路由导航过程中:全局的, 单个路由独享的, 或者组件级的。

简单的说,导航守卫就是路由跳转过程中的一些钩子函数。路由跳转是一个大的过程,这个大的过程分为跳转前中后等等细小的过程,在每一个过程中都有一函数,这个函数能让你操作一些其他的事儿,这就是导航守卫。类似于组件生命周期钩子函数

  1. 全局守卫 : 全局守卫是路由对象的 router (路由的实例对象)
              前置全局守卫  beforeEach           进入路由之前
              全局解析守卫  beforeResolve    	动态路由切换时会触发该守卫
              全局后置守卫  afterEach			离开路由
2. 路由独享守卫 : 路由专享, 在路由的配置项中使用的一个属性
           beforeEnter       
3. 组件内守卫 : 组件专享, 在路由组件中添加的钩子函数
            beforeRouteEnter    进入路由
            beforeRouteUpdate (2.2 新增)    切换(更新)路由
            beforeRouteLeave       离开路由

每个守卫都有三个参数:

to:这是你要跳去的路由对象。

from:这是你要离开的路由对象。

next:是一个方法,它接受参数。这个方法必须调用要不就跳不过去了,你可以把它看做保安。必须给它打个招呼,要不然不让你过。

next()。这就是告诉保安我要过去,去哪里呢? 就是to了。
next(false)。如果传入false。保安就不让过了。也就是中断跳转。
next({path:“/”})。这个意思是保安不让过,并把你交到另一地方审查了。也就是中断跳转,跳转到一个新的路径。

(1)
在这里插入图片描述
(2)
当进入到路由页面触发

在这里插入图片描述

beforeRouteUpdate 动态路由切换时会触发该守卫
在这里插入图片描述
在这里插入图片描述将url中的地址清空或换一个地址,动态路由的切换不算离开路由

在这里插入图片描述

<body>
    <div id="app">
        <router-view></router-view>
    </div>
    <script src="./js/vue.js"></script>
    <script src="./js/vue-router.js"></script>
    <script>
        //   路由组件
        const order = {
            template: '<div>order 订单页</div>',
            beforeRouteEnter(to, from, next) {
                console.log('(3)组件内守卫 beforeRouteEnter 进入路由');
                next()
            },
            //   beforeRouteUpdate 动态路由切换时会触发该守卫
            beforeRouteUpdate(to, from, next) {
                console.log('(3)组件内守卫 beforeRouteUpdate 切换路由');
                next()
            },
            beforeRouteLeave(to, from, next) {
                console.log('(3)组件内守卫 beforeRouteLeave 离开路由');
                next()
            }
        }
        const list = {
            template: '<div>list 列表页</div>'
        }

        //   路由配置
        const routes = [{
            path: '/order/:id',
            component: order,
            //路由独享守卫
            beforeEnter: function(to, from, next) {
                console.log('(2)路由独享守卫@@@@@@');
                // console.log(to);
                // console.log(from);
                next()
            }

        }, {
            path: '/list',
            component: list
        }]

        const router = new VueRouter({
            routes
        })

        //  1----前置全局守卫  所有的路由在匹配之前都会被拦截 
        //  接受参数: to(到哪去), from(从哪来),  next(放行, 还可以进行重定向)
        router.beforeEach((to, from, next) => {
            //  放行
            console.log(' 前置全局守卫 !!!');
            // console.log(to);
            // console.log(from);
            next()
        })

        router.beforeResolve((to, from, next) => {
            console.log(' 全局解析守卫 !!!');
            next()
        })

        router.afterEach((to, from) => {
            console.log(' 全局后置钩子!!! ');
        })
        const app = new Vue({
            el: '#app',
            router
        })
    </script>
</body>
前置全局守卫beforeEach:/及路由元信息
    路由 元信息 meta 属性:
        如果你想在路由中添加自定义的属性和信息,可以使用 meta 属性

    路由对象的 matched 属性: 包含了所有的路由信息对象,(也包含元信息 meta 属性,父路由和子路由都包含)

示例:

{
        path: '/home',
        component: home,
        meta: {
            //   自定义的路由传递的信息
            ticket: false //false就是不需要买票
        }
    }

在这里插入图片描述

一个路由匹配到的所有路由记录为 $route 对象(还有在导航守卫中的路由对象)的 $route.matched 数组。因此,我们需要遍历 $route.matched 来检查路由记录中的 meta 字段。

to.matched.map(item => {
                if (item.meta.ticket) {//判断自定义路由传递的信息
                下步操作
 }

在这里插入图片描述

to.matched.some()

if (to.matched.some(record => record.meta.属性) ),
如果对这类写法不熟悉,可以去看看es6的箭头函数,
这句话就是返回遍历的某个路由对象,我们定义为为record,检测这个对象是否拥有meta这个对象,
如果有meta这个对象,检测它的meta对象是不是有meta中属性,且为true,
 router.beforeEach((to, from, next) => {
            console.log(to);//to要去的地方
            //  判断是否需要买票
            if (to.matched.some(route => route.meta.ticket)) { //
                // 判断是否有票
                if (localStorage.getItem('ticket')) {//如果有票放行
                    next()
                } else {
                    // next('/ticket')
                    next({
                        path: '/ticket',//如果没有票,跳转到买票页面,同时传参说明你是哪个地方来的
                        query: {
                             // from: to.path // from=%2Fzoom    传递的参数,格式不是我们想要的 ,下面去除%
                            from: to.path.substring(1)
                        }
                    })
                }
            } else {
                next()
            }
        })
//买票页
 const ticket = {
            template: `
                <div>
                    购票处
                    <button @click='buyTicket'>买票</button>
                    <router-link to='/home'>回家</router-link>
                </div>
             `,
            methods: {
                buyTicket() {
                    //  把票存储到本地
                    localStorage.setItem('ticket', "票")
                        //  买完票后可以进入目的地  获取路由参数  
                    let from = this.$route.query.from
                    this.$router.push({
                        path: `/${from}`//买完票直接跳转进入到你来的地方
                    })
                }
            }
        }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值