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> {{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 pageh1> <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')">跳转到parentbutton> <button @click="handleClick('replace')">替换到parentbutton> 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 组件内的守卫
{{ food }}
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' }