路由进阶

 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'
}

转载于:https://www.cnblogs.com/qicao/p/10781099.html

Published by

风君子

独自遨游何稽首 揭天掀地慰生平