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