zoukankan      html  css  js  c++  java
  • 路由进阶

     1>路由组件传参

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

    解决方法:

    1.1若是动态匹配页面,只需要在路由参数中加入props:true即可。

    import Home from "@/views/Home.vue";
    
    export default [
      {
        path: "/argu/:name",
        name:"argu",
        component: () => import("@/views/argu.vue"),
        props:true//可以进行路由组件传参
      }
    ];
    <template>
      <div>
        <!-- 拿到动态路由的参数 -->
        <!-- {{$route.params.name}} -->
        <!-- 尽量使用这种方法,不要使用this.$route.paramas,让组件和路由解耦尽量不要在组件中使用$routes,$router方法 -->
        {{name}}
      </div>
    </template>
    
    <script>
    export default {
      //
      props:{
        name:{
          type:String,
          default:"caoqi"
        }
      }
    };
    </script>

    2.如果是普通的页面,则也可使用props对象格式传递:

    import Home from "@/views/Home.vue";
    
    export default [
      {
        path: "/about",
        name: "about",
        // route level code-splitting
        // this generates a separate chunk (about.[hash].js) for this route
        // which is lazy-loaded when the route is visited.
        component: () => import(/* webpackChunkName: "about" */ "@/views/About.vue"),
        //如果是空对象则显示apple
      //props:{},
        props: {
          food:'banaa'
        }
      },
      {
        path: "/argu/:name",
        name:"argu",
        component: () => import("@/views/argu.vue"),
        props:true//可以进行路由组件传参
      }
    ];
    <template>
      <div class="about">
        <h1>This is an about page</h1>
        <b>{{ food }}</b>
      </div>
    </template>
    <script>
    export default {
      props:{
        food:{
          type:String,
          default:"apple"
        }
      }
    }
    </script>

     3.如果是普通的页面,还可以使用props函数模式传递,这种情况适合于根据地址参数做一些逻辑:

    import Home from "@/views/Home.vue";
    
    export default [
      {
        path: "/",
        alias:'/home_page',
        name: "home", //加上name属性  命名路由
        component: Home,
        props: route => ({ 
          food:route.query.food
        })
      }
    ];
    <template>
      <div class="home">
        <b>{{ food }}</b>
        <button @click="handleClick('back')">返回上一页</button>
        <button @click="handleClick('push')">跳转到parent</button>
        <button @click="handleClick('replace')">替换到parent</button>
      </div>
    </template>
    
    <script>
    // @ is an alias to /src
    import HelloWorld from '@/components/HelloWorld.vue'
    
    export default {
      name: 'home',
      components: {
        HelloWorld
      },
      props:{
        food:{
          type:String,
          default:"apple"
        }
      },
      methods:{
        handleClick(type){
          if (type==="back") {
            //this.$router.back();
            this.$router.go(-1);
          }else if (type==="push") {
            const name="caoqi";
            //使用push会在浏览器中加入一个记录
            //使用路径跳转
            //this.$router.push("/parent");
            //还可以使用命名路由的方式:
            this.$router.push({
              // name: "parent",
              // //加入name参数,http://localhost:8080/#/parent?name=caoqi
              // query: {
              //   name: 'caoqi'
              // }
    
              // name: "argu",
              // //加入name参数,http://localhost:8080/#/argu/caoqi
              // params: {
              //   name: 'caoqi'
              // }
    
    
              //ES6写法:
              path:`/argu/${name}`,
            })
          }else if (type==="replace") {
            //使用replace不会在浏览历史中加入记录
            this.$router.replace({
              name: 'parent'
            })
          }
        }
      }
    }
    </script>

    2>HTML histoty模式

    import Vue from "vue";
    import Router from "vue-router";
    import routes from "./router";
    
    Vue.use(Router);
    
    export default new Router({
      //mode:'hash',//默认模式
      mode:'history',
      routes: routes
    });

    3>导航守卫(路由守卫)

    路由跳转前做一些验证,比如登录验证,是网站中的普遍需求。

    官方api地址:https://router.vuejs.org/zh-cn/advanced/navigation-guards.html

    3.1 全局守卫

    3.1.1 全局前置守卫

    import Vue from "vue";
    import Router from "vue-router";
    import routes from "./router";
    
    Vue.use(Router);
    
    const router = new Router({
      routes
    });
    
    const HAS_LOGINED = false;
    //全局前置守卫
    /*
    to: Route: 即将要进入的目标 路由对象
    from: Route: 当前导航正要离开的路由
    next: Function: 一定要调用该方法来 resolve 这个钩子
     */
    //模拟登陆验证逻辑:当跳转页面为登陆页面且已经登陆时,直接跳转到home页面,如果跳转页面不为登录页且已经登陆,则继续执行,否则直接跳转到登录页
    router.beforeEach((to, from, next) => {
      if (to.name !== "login") {
        if (HAS_LOGINED) next();
        else next({ name: "login" });
      } else {
        if (HAS_LOGINED) next({ name: "home" });
        else next();
      }
    });
    
    export default router;

    3.1.2 全局后置钩子

    3.2 路由独享的守卫

    import Home from "@/views/Home.vue";
    
    export default [
      {
        path: "/",
        alias: "/home_page",
        name: "home", //加上name属性  命名路由
        component: Home,
        props: route => ({
          food: route.query.food
        }),
        beforeEnter: (to, from, next) => {
          // if (from.name === "about") alert("这是从about来的");
          // else alert("这不是从about来的");
          next();
        }
      }
    ];

    3.3 组件内的守卫

    <template>
      <div class="home">
        <b>{{ food }}</b>
        <button @click="handleClick('back')">返回上一页</button>
        <button @click="handleClick('push')">跳转到parent</button>
        <button @click="handleClick('replace')">替换到parent</button>
      </div>
    </template>
    
    <script>
    // @ is an alias to /src
    import HelloWorld from '@/components/HelloWorld.vue'
    
    export default {
      name: 'home',
      components: {
        HelloWorld
      },
      props:{
        food:{
          type:String,
          default:"apple"
        }
      },
      beforeRouteEnter (to, from, next) {
        // 在渲染该组件的对应路由被 confirm 前调用
        // 不!能!获取组件实例 `this`
        // 因为当守卫执行前,组件实例还没被创建
        next(vm => {
          //若想使用实例,可使用这种方法
          console.log(vm)
        })
      },
     //这个离开守卫通常用来禁止用户在还未保存修改前突然离开。该导航可以通过 next(false) 来取消。
      beforeRouteLeave (to, from, next) {
        // const leave = confirm('您确定要离开吗?')
        // if (leave) next()
        // else next(false)
        next()
      }
    }
    </script>

    4>路由元信息

    import Home from "@/views/Home.vue";
    
    export default [
      {
        path: "/",
        alias: "/home_page",
        name: "home", //加上name属性  命名路由
        component: Home,
        props: route => ({
          food: route.query.food
        }),
        beforeEnter: (to, from, next) => {
          // if (from.name === "about") alert("这是从about来的");
          // else alert("这不是从about来的");
          next();
        }
      },
      {
        path: "/about",
        name: "about",
        // route level code-splitting
        // this generates a separate chunk (about.[hash].js) for this route
        // which is lazy-loaded when the route is visited.
        component: () =>
          import(/* webpackChunkName: "about" */ "@/views/About.vue"),
        props: {
          food: "banaa"
        },
        meta: {
          title: '关于'
        }
      }
    ];

    index.js

    import Vue from "vue";
    import Router from "vue-router";
    import routes from "./router";
    import { setTitle } from "@/lib/util";
    
    Vue.use(Router);
    
    const router = new Router({
      routes
    });
    
    const HAS_LOGINED = true;
    //全局前置守卫
    /*
    to: Route: 即将要进入的目标 路由对象
    from: Route: 当前导航正要离开的路由
    next: Function: 一定要调用该方法来 resolve 这个钩子
     */
    //模拟登陆验证逻辑:当跳转页面为登陆页面且已经登陆时,直接跳转到home页面,如果跳转页面不为登录页且已经登陆,则继续执行,否则直接跳转到登录页
    router.beforeEach((to, from, next) => {
      to.meta && setTitle(to.meta.title);
      if (to.name !== "login") {
        if (HAS_LOGINED) next();
        else next({ name: "login" });
      } else {
        if (HAS_LOGINED) next({ name: "home" });
        else next();
      }
    });
    
    export default router;

    util.js

    export const setTitle = (title) => {
      window.document.title = title || 'admin'
    }

  • 相关阅读:
    蓄水池抽样(Reservoir Sampling )
    动态申请一个二维数组
    最大子段和问题分析和总结
    正则表达式语法
    正则表达式介绍
    小刘同学的第七十六篇博文
    小刘同学的第七十五篇博文
    小刘同学的第七十四篇博文
    小刘同学的第七十三篇博文
    小刘同学的第七十二篇博文
  • 原文地址:https://www.cnblogs.com/qicao/p/10781099.html
Copyright © 2011-2022 走看看