react router @4 和 vue路由 詳解(全)

react router @4 和 vue路由

本文大綱:javascript

一、vue路由基礎和使用html

二、react-router @4用法vue

三、什麼是包容性路由?什麼是排他性路由?java

四、react路由有兩個重要的屬性:children和render的區別?react

五、react如何在路由裏面定義一個子路由?vue-router

六、vue如何在路由裏面定義一個子路由?npm

七、react怎麼經過路由傳參?api

八、vue怎麼經過路由傳參?數組

九、怎麼在react裏拿到router對象?瀏覽器

十、怎麼在vue裏拿到router對象?

十一、路由怎麼回退?

十二、react路由守衛?

1三、vue路由守衛?

 


 

一、vue路由基礎和使用

  a、大概目錄

           我這裏建了一個router文件夾,文件夾下有index.html

 


 

  

  b、準備工做:

    npm install vue-router

    或者 yarn add vue-router

  


 

 

  c、配置

    必需要經過 Vue.use() 明確地安裝路由功能:
    在你的文件夾下的 src 文件夾下的 main.js 文件內寫入如下代碼

import Vue from 'vue'

import VueRouter from 'vue-router'

Vue.use(VueRouter)

    附上個人代碼:我是將router的內容寫在了個人router文件夾下的index.html中,而後暴露出去,在main.js中引入

    router文件夾下的index.html

import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)

import Home from 'pages/Home'
import Map from 'components/Map'
import Home1 from 'components/Home1'
import Find from 'components/Find'
import Mine from 'components/Mine'
import Type from 'components/Type'
import Publish from 'components/Publish'
import Search from 'components/Search'
import Success from 'components/Success'
import Need from 'components/Need'
import Position0 from 'components/Position'
import Like from 'components/scrollX/Like'
import S1 from 'components/scrollX/1'
import S2 from 'components/scrollX/2'
import Listall from 'components/mine/Listall'
import Listone from 'components/mine/Listone'
import Listchange from 'components/mine/Listchange'

const routes = [
    {
        path:'/',
        redirect:'/ho'
    },
    {
        path: '/ho',
        redirect:'/ho/home',
        component: Home,
        children: [
            {
                name: 'home',
                path: 'home',
                component: Home1,
                redirect:'/ho/home/like',
                children :[
                    {
                        name: 'like',
                        path: 'like',
                        component: Like
                    },
                    {
                        name: '2000001',
                        path: '2000001',
                        component: S1
                    },
                    {
                        name: '2000022',
                        path: '2000022',
                        component: S2
                    }
                ]
            },
            {
                name: 'type',
                path: 'type',
                component: Type
            },
            {
                name: 'need',
                path: 'need',
                component: Need
            },
            {
                name: 'find',
                path: 'find',
                component: Find
            },
            {
                name: 'mine',
                path: 'mine',
                component: Mine
            }
        ]
    },
    {
        name: 'search',
        path: '/search',
        component: Search
    },
    {
        name: 'position',
        path: '/position',
        component: Position0
    },
    {
        name: 'publish',
        path: '/publish',
        component: Publish
    },
    {
        name: 'success',
        path: '/success',
        component: Success
    },
    {
        name: 'listall',
        path: '/listall',
        component: Listall
    },
    {
        name: 'listone',
        path: '/listone',
        component: Listone
    },
    {
        name: 'listchange',
        path: '/listchange',
        component: Listchange
    },
    {
        name: 'map',
        path: '/map',
        component: Map
    }
]

const router = new VueRouter({
    mode: 'history',
    routes
})

export default router

    main.js

import Vue from 'vue'
import App from './App.vue'
import router from './router'

Vue.use(MintUI)
Vue.use(ElementUI);

Vue.config.productionTip = false

new Vue({
  router,
  render: h => h(App)
}).$mount('#app')

 


 

  d、常規使用

     <router-view></router-view>路由匹配到的組件將渲染在這裏
    你能夠把他理解爲一個版塊,好比如今有一個home頁面,分爲兩部分,內容部分和ibar部分,如圖:
    
    這五個頁面共用下面的導航欄,只有導航欄上面的內容不一樣
    <router-view></router-view>就能夠寫在<Ibar></Ibar>的上面
<template>
    <div class="home">
        <router-view></router-view>
        <Ibar></Ibar>
    </div>
</template>

    那麼在Ibar頁面中如何切換路由呢?

<template>
    <div class="ibar">
        <router-link to="/ho/home" tag="span" active-class="active">首頁</router-link>
        <router-link to="/ho/type" tag="span" active-class="active">類別</router-link>
        <router-link to="/ho/need" tag="span" active-class="active">需求</router-link>
        <router-link to="/ho/find" tag="span" active-class="active">發現</router-link>
        <router-link to="/ho/mine" tag="span" active-class="active">個人</router-link>
    </div>
</template>

    注意:此處的tag=「span」表明這個按鈕是個span標籤,你能夠寫樣式的時候直接寫span標籤的樣式便可

       此處的active-class="active"表明點擊哪一個按鈕哪一個按鈕高亮

    

    此時咱們詳細看一下router文件夾下的index.js

//引入vue  

import Vue from
'vue'

//引入路由
import VueRouter from 'vue-router'

//把路由掛載到vue上
Vue.use(VueRouter)
//引入我各個路由對應的component組件
import Home from
'pages/Home' import Map from 'components/Map' import Home1 from 'components/Home1' import Find from 'components/Find' import Mine from 'components/Mine' import Type from 'components/Type' import Publish from 'components/Publish' import Search from 'components/Search' import Success from 'components/Success' import Need from 'components/Need' import Position0 from 'components/Position' import Like from 'components/scrollX/Like' import S1 from 'components/scrollX/1' import S2 from 'components/scrollX/2' import Listall from 'components/mine/Listall' import Listone from 'components/mine/Listone' import Listchange from 'components/mine/Listchange'
const routes
= [ {

     //path是路由的路徑
path:
'/',

     //redirect表明重定向,由於當前路徑'/'並無對應的組件,因此須要重定向到其餘路由頁面
     redirect:
'/ho' }, { path: '/ho', redirect:'/ho/home',

     //當不須要重定向的時候,須要component寫上當前路由對應的組件頁面
component: Home,

     //有些路由還有子路由,須要用到children[],
     //當訪問的時候,<router-link>的屬性to的時候要把全部的父組件都帶上
     //如:此處的/ho/home/like
children: [ { name:
'home', path: 'home', component: Home1, redirect:'/ho/home/like', children :[ { name: 'like', path: 'like', component: Like }, { name: '2000001', path: '2000001', component: S1 }, { name: '2000022', path: '2000022', component: S2 } ] }, { name: 'type', path: 'type', component: Type }, { name: 'need', path: 'need', component: Need }, { name: 'find', path: 'find', component: Find }, { name: 'mine', path: 'mine', component: Mine } ] }, { name: 'search', path: '/search', component: Search }, { name: 'position', path: '/position', component: Position0 }, { name: 'publish', path: '/publish', component: Publish }, { name: 'success', path: '/success', component: Success }, { name: 'listall', path: '/listall', component: Listall }, { name: 'listone', path: '/listone', component: Listone }, { name: 'listchange', path: '/listchange', component: Listchange }, { name: 'map', path: '/map', component: Map } ] const router = new VueRouter({

//此處設置mode爲history,即不帶#號,在處理數據的時候會更方便一些
    mode: 'history',

//ES6的寫法,即routes:routes的簡寫,當key和value名字同樣時,可簡寫
routes })
//把你建立的路由暴露出去,使得main.js能夠將其引入並使用
export
default router

    引伸1:

    路由有一個meta屬性

    能夠給該路由掛載一些信息

    設置一些本身title、顯示隱藏、左右滑動的方向之類的

meta: {
      title: "HelloWorld",    要現實的title
      show: true               設置導航隱藏顯示
}

    使用的時候:this.$route.meta.show

    <Bottom v-show="this.$route.meta.show"></Bottom>

 

    引伸2:

    動態路由

{
    path:"/two/:id",
    component:Two,
}

    獲取數據this.$route.params.動態路由的名字

    此處是:this.$route.params.id

 

    引伸3:

    路由別名alias

{ 
    path: '/a', 
    component: A, 
    alias: '/b' 
}
//  /a 的別名是 /b
//意味着,當用戶訪問 /b 時,URL 會保持爲 /b,可是路由匹配則爲 /a
//就像用戶訪問 /a 同樣
//簡單的說就是給 /a 起了一個外號叫作 /b ,可是本質上仍是 /a

 


 

二、react-router @4用法

  a、大概目錄

       不須要像vue那樣麻煩的用到一個單獨的文件夾,react只須要在index.js中部分配置便可

 


 

  b、準備工做

     yarn add react-router-dom

 

   index.js中

     import { BrowserRouter } from 'react-router-dom'

     

          <BrowserRouter>
            <App />
          </BrowserRouter>
    這樣App內部組件均可以使用
 

 
  c、使用
       一樣是上面那個例子,寫法不同:
import React, { Component } from 'react';
import {Bar} from 'components/common/ibar'

import ShopDetail from 'pages/shopDetail/shopDetail'

import NodeDe from 'pages/noteDetail/NodeDe'

import Car from 'pages/car/Car'

import Admin from 'pages/admin/Admin'

import Admin1 from 'pages/admin/Admin1'

import GoodDetail from 'pages/goodDetail/goodDetail'

import { Route, Switch, Redirect } from 'react-router-dom'

class App extends Component {
  render() {
    return (

    //這裏爲何要用Switch包裹呢?
    //<Switch>是惟一的由於它僅僅只會渲染一個路徑
<Switch>

     //Redirect表明重定向,若是加了exact表明精準匹配
<Redirect exact from="/" to="/home"></Redirect> <Route path='/home' component={Bar}/> <Route path="/shopDetail/:shopId/:shopName/:shopNote/:shopPic" component={ShopDetail} /> <Route path='/noteDetail/:noteId' component={NodeDe} /> <Route path='/goodDetail/:goodId/:shopId' component={GoodDetail} /> <Route path='/car' component={Car} /> <Route path='/admin' component={Admin}/> <Route path='/admin1/:phone' component={Admin1}/> </Switch> ); } } export default App;

 

    當點擊哪裏須要跳轉的時候,在標籤外面包一個<Link to= ' 路由路徑 ' ></Link>         

            

    動態路由/xxx/:xx,如上圖

    

    引伸1:HashRouter和BrowserRouter

      它們兩個是路由的基本,就像蓋房子必須有地基同樣

      咱們須要將它們包裹在最外層,咱們只要選擇其一就能夠了。

      如今講它們的不一樣:

     HashRouter

       若是你使用過react-router2或3或者vue-router

       你常常會發現一個現象就是url中會有個#,

                 例如localhost:3000/#

                 HashRouter就會出現這種狀況,它是經過hash值來對路由進行控制

                 若是你使用HashRouter,你的路由就會默認有這個#。

         

       BrowserRouter

                 不少狀況下咱們則不是這種狀況,咱們不須要這個#

       由於它看起來很怪,這時咱們就須要用到BrowserRouter。

 

    引伸2:Link和NavLink的選擇

      二者都是能夠控制路由跳轉的,不一樣點是NavLink的api更多,更加知足你的需求。

         Link:主要api是to,to能夠接受string或者一個object,來控制url

      

  

      NavLink:它能夠爲當前選中的路由設置類名、樣式以及回調函數等。

             

 

    引伸3:withRouter高階組件

//引入withRouter
import { Link, withRouter } from
'react-router-dom' //代碼結尾暴露的時候,把要暴露的組件包裹在withRouter中,作成一個高階組件,
//將react-router 的 history,location,match 三個對象傳入
//將組件包一層withRouter,就能夠拿到須要的路由信息
//獲取路由信息的時候
this.props.location
withRouter(GoodDetail)

withRouter(connect(mapState, mapDispatch)(GoodDetail))

 

 


 

 

三、什麼是包容性路由?什麼是排他性路由?

  

  包容性路由:

    若是路由有/food 和 /food/1 那麼在匹配 /food 的時候兩個都能匹配到

    react就是典型的包容性路由

    因此react須要引入Switch標籤,把路由變成排他性的

  

  排他性路由: 

    只要匹配成功一個就不會往下面進行匹配了

    vue是排他性路由

    匹配從上到下,匹配到一個即止

 


 

四、react路由有兩個重要的屬性:children和render,這兩個有什麼區別?

  a、Route 能夠寫行間render,render={()=>{return }}
 
  b、也能夠寫行間children={()={return }}
 
  c、無論匹配與否children都執行
 
  d、render優先級比children高

  


 
五、react如何在路由裏面定義一個子路由?
 
  a、引入在須要子路由的頁面引入Route標籤  
 
   <Route path='/noteDetail/home' component={NodeDe} />

  b、舉個🌰(糖炒栗子,個人愛,爲何我本身作的🌰都那麼難吃???)

 

    

 

    咱們在home頁面裏(左邊一溜的父組件)該點擊的地方

export const Home = () => (
  <ul>
    <li>
      <NavLink to='/home' exact activeStyle ={selectedStyle}>首頁</NavLink>
    </li>
    <li>
      <NavLink to='/about' activeStyle ={selectedStyle}>關於咱們</NavLink>
    </li>
    <li>
      <NavLink to='/event' activeStyle ={selectedStyle}>企業事件</NavLink>
    </li>
    <li>
      <NavLink to='/product' activeStyle ={selectedStyle}>公司產品</NavLink>
    </li>
    <li>
      <NavLink to='/us' activeStyle ={selectedStyle}>聯繫咱們</NavLink>
    </li>
  </ul>
)

     咱們在home頁面裏(左邊一溜的父組件)設置內容應該不一樣的地方

      <Redirect exact from="/" to="/home"></Redirect>
      <Route path='/home' exact component={Home}/>
      <Route path='/about' component={About}/>
      <Route path='/event' component={Event}/>
      <Route path='/product' component={Product}/>    
      <Route path='/us' component={Us}/>    

 

    咱們在關於咱們頁面該點擊的地方

export const AboutMenu = () => (
  <ul className="about-menu">
    <li>
      <NavLink to='/about' exact activeStyle ={selectedStyle}>公司簡介</NavLink>
    </li>
    <li>
      <NavLink to='/about/history' activeStyle ={selectedStyle}>公司歷史</NavLink>
    </li>
    <li>
      <NavLink to='/about/services' activeStyle ={selectedStyle}>公司服務</NavLink>
    </li>
    <li>
      <NavLink to='/about/location' activeStyle ={selectedStyle}>企業位置</NavLink>
    </li>
  </ul>
)

    咱們在關於咱們頁面該實現內容不一樣的地方

      <Route path='/about' exact component={Company}/>
      <Route path='/about/history' component={History}/>
      <Route path='/about/services' component={Services}/>
      <Route path='/about/location' component={Location}/>

 

    由此便實現了react子路由

 


 

 

六、vue如何在路由裏面定義一個子路由?

  給父路由加一個 children:[]

  參考個人<1.d>的代碼

const routes = [
    {

     //path是路由的路徑

        path:'/',

     //redirect表明重定向,由於當前路徑'/'並無對應的組件,因此須要重定向到其餘路由頁面
    
        redirect:'/ho'
    },
    {
        path: '/ho',
        redirect:'/ho/home',

     //當不須要重定向的時候,須要component寫上當前路由對應的組件頁面

        component: Home,

     //有些路由還有子路由,須要用到children[],
     //當訪問的時候,<router-link>的屬性to的時候要把全部的父組件都帶上
     //如:此處的/ho/home/like

        children: [

      //子路由寫在children數組裏,仍舊以對象的形式

{ name:
'home', path: 'home', component: Home1, redirect:'/ho/home/like', children :[ { name: 'like', path: 'like', component: Like }, { name: '2000001', path: '2000001', component: S1 }, { name: '2000022', path: '2000022', component: S2 } ] }, { name: 'type', path: 'type', component: Type }, { name: 'need', path: 'need', component: Need }, { name: 'find', path: 'find', component: Find }, { name: 'mine', path: 'mine', component: Mine } ] }, { name: 'search', path: '/search', component: Search }, { name: 'position', path: '/position', component: Position0 }, { name: 'publish', path: '/publish', component: Publish }, { name: 'success', path: '/success', component: Success }, { name: 'listall', path: '/listall', component: Listall }, { name: 'listone', path: '/listone', component: Listone }, { name: 'listchange', path: '/listchange', component: Listchange }, { name: 'map', path: '/map', component: Map } ] const router = new VueRouter({ //此處設置mode爲history,即不帶#號,在處理數據的時候會更方便一些 mode: 'history', //ES6的寫法,即routes:routes的簡寫,當key和value名字同樣時,可簡寫 routes }) //把你建立的路由暴露出去,使得main.js能夠將其引入並使用 export default router

 


 

七、react怎麼經過路由傳參?

  a、通配符傳參(刷新頁面數據不丟失)

//在定義路由的時候

<Route path='/path/:本身起個名字' component={Path}/>


//在路由點擊跳轉的時候

<Link to="/path/你要傳的參數">通配符</Link>


//另外一個頁面接收傳來的參數

this.props.match.params.你起的名字

  

       舉個🌰

       

     另外一個頁面接收值的時候:

        this.props.match.params.id

 

  b、query傳參(刷新頁面數據丟失)

//路由定義

<Route path='/query' component={Query}/>

//跳轉的時候
var query = {
        pathname: '/query',
        query: '我是經過query傳值 '
}

<Link to={query}>query</Link>

//另外一個頁面使用的時候

this.props.location.query

這裏的this.props.location.query === '我是經過query傳值'

 

  c、state傳參(刷新頁面數據丟失,同query差很少,只是屬性不同,並且state傳的參數是加密的,query傳的參數是公開的) 

//Route定義

<Link to={state}>state</Link>

//使用的時候

    var state = {
        pathname: '/state',
        state: '我是經過state傳值'
    }
    <Route path='/state' component={State}/>

//另外一個頁面獲取值的時候

this.props.location.state

這裏的this.props.location.state === '我是經過query傳值'

 

  d、路由?傳參數

           

     此處的foodmenu經過路由?後面傳參數

     在另外一個頁面的this.props.location.search能夠獲取到 "?id=6" 

 


 

八、vue怎麼經過路由傳參?

  a、通配符傳參數

//在定義路由的時候

{
     path: '/describe/:id',
     name: 'Describe',
     component: Describe
}

//在使用的時候

this.$router.push({
       path: `/describe/${id}`,
})

//接收頁面獲取值

this.$route.params.id

 

  b、params傳參,跳轉的時候不會顯示在url上

//在定義路由的時候

{
     path: '/describe',
     name: 'Describe',
     component: Describe
}

//在使用的時候

this.$router.push({
      name: 'Describe',
      params: {
            id: id
      }
})

//接收頁面獲取值

this.$route.params.id

 

  c、query傳參,傳餐的時候在url顯示? key=value & key=value

//在定義路由的時候

   {
     path: '/describe',
     name: 'Describe',
     component: Describe
   }

//在使用的時候

 this.$router.push({
          path: '/describe',
          query: {
            id: id
          }
 })

//接收頁面獲取值
this.$route.query.id

 


 

 

九、怎麼在react裏拿到router對象?

  import withRouter 而且 export組件的時候,用withRouter把組件包起來

//引入withRouter
import {
    Link,
    withRouter
} from 'react-router-dom'

//代碼結尾暴露的時候,把要暴露的組件包裹在withRouter中,作成一個高階組件,
//將react-router 的 history,location,match 三個對象傳入
//將組件包一層withRouter,就能夠拿到須要的路由信息
//獲取路由信息的時候this.props.location
withRouter(GoodDetail)

withRouter(connect(mapState, mapDispatch)(GoodDetail))

 


 

 

十、怎麼在vue裏拿到router對象? 

//在使用的時候

 this.$router.push({
          path: '/describe',
          query: {
            id: id
          }
 })

//接收頁面獲取值
this.$route.query.id

 


 

十一、路由怎麼回退?

  a、vue:this.$router.back(-1)

  b、react:this.props.history.goback()

 


 

 

十二、react路由守衛?

  a、在以前的版本中,React Router 也提供了相似的 onEnter 鉤子,但在 React Router 4.0 版本中,取消了這個方法。

  b、那麼在react中若是咱們也須要路由守衛怎麼辦?好比在跳轉路由前須要判斷用戶是否登陸?若是登陸才能夠進行跳轉,不然沒有權限

  c、

//下面是個人實現方式,
//首先,準備一份路由表,
//包含了路由的地址,組件以及是否須要權限校驗:

import { HomePage } from '../pages/home/home.page';
import { LoginPage } from '../pages/login/login.page';
import { ErrorPage } from '../pages/error/error.page';

interface routerConfigModel {
    path:string,
    component?:any,
    auth?:boolean
}

export const routerConfig:routerConfigModel[] = [
    {
        path:'/',
        component:HomePage,
        auth:true,
    },
    {
        path:'/home',
        component:HomePage,
        auth:true,
    },
    {
        path:'/login',
        component:LoginPage,
    },
    {
        path:'/404',
        component:ErrorPage
    }
];

//將 auth 設置爲 true,表示該路由須要權限校驗。
//而後,定義 Router 組件,該組件是通過高階組件包裝後的結果:

import * as React from 'react';
import { HashRouter,Switch } from 'react-router-dom';
import { FrontendAuth } from '../components/frontend-auth/frontend-auth.component'
import { routerConfig } from './router.config'

export class Router extends React.Component{
    render(){
        return(
            <HashRouter>
                <Switch>
                    <FrontendAuth config={routerConfig} />
                </Switch>
            </HashRouter>
        );
    }
}


//全部的路由跳轉,都交給 FrontendAuth 高階組件代理完成。
//下面是 FrontendAuth 組件的實現:

import * as React from 'react';
import { Route,Redirect } from 'react-router-dom';
import { propsModel } from './frontend-auth.model'

export class FrontendAuth extends React.Component<any,propsModel>{
    render(){
        const { location,config } = this.props;
        const { pathname } = location;
        const isLogin = localStorage.getItem('__config_center_token')
        
        // 若是該路由不用進行權限校驗,登陸狀態下登錄頁除外
        // 由於登錄後,沒法跳轉到登錄頁
        // 這部分代碼,是爲了在非登錄狀態下,訪問不須要權限校驗的路由
        
        const targetRouterConfig = config.find((v:any) => v.path === pathname);
        if(targetRouterConfig && !targetRouterConfig.auth && !isLogin){
            const { component } = targetRouterConfig;
            return <Route exact path={pathname} component={component} />
        }

        if(isLogin){
            // 若是是登錄狀態,想要跳轉到登錄,重定向到主頁
            if(pathname === '/login'){
                return <Redirect to='/' />
            }else{
                // 若是路由合法,就跳轉到相應的路由
                if(targetRouterConfig){
                    return <Route path={pathname} component={targetRouterConfig.component} />
                }else{
                    // 若是路由不合法,重定向到 404 頁面
                    return <Redirect to='/404' />
                }
            }
        }else{
            // 非登錄狀態下,當路由合法時且須要權限校驗時,跳轉到登錄頁面,要求登錄
            if(targetRouterConfig && targetRouterConfig.auth){
                return <Redirect to='/login' />
            }else{
                // 非登錄狀態下,路由不合法時,重定向至 404
                return <Redirect to='/404' />
            }
        }
    }
}

//以及對應的 Model:

export interface propsModel {
    config:any[],
}

//頁面上的路由跳轉,都由 FrontendAuth 高階組件代理了,
//在 Switch 組件內部,再也不是 Route 組件,
//而只有一個 FrontendAuth 組件。


//FrontendAuth 組件接收一個名爲 config 的 Props,這是一份路由表。
//同時,因爲 FrontendAuth 組件放在了 Switch 組件內部,React Router 還自動爲 FrontendAuth 注入了 location 屬性,
//當地址欄的路由發生變化時,就會觸發 location 屬性對象上的 pathname 屬性發生變化,
//從而觸發 FrontendAuth 的更新(調用 render 函數)。

//FrontendAuth 的 render 函數中,
//根據 pathname 查找到路由表中的相關配置,
//若是該配置中指定了無需校驗,就直接返回相應的 Route 組件。
//若是查找到的配置須要進行校驗,再根據是否登錄進行處理,具體能夠查看代碼中的註釋。

總結一下,實現路由守衛須要考慮到如下的問題:

未登陸狀況下,訪問不須要權限校驗的合法頁面:容許訪問
登錄狀況下,訪問登錄頁面:禁止訪問,跳轉至主頁
登錄狀況下,訪問除登錄頁之外的合法頁面:容許訪問
登錄狀況下,訪問全部的非法頁面:禁止訪問,跳轉至 404
未登陸狀況下,訪問須要權限校驗的頁面:禁止訪問,跳轉至登錄頁
未登陸狀況下,訪問全部的非法頁面:禁止訪問,跳轉至 404
    

 

1三、vue路由守衛

  a、beforeEach

  全局守衛

(每一個路由調用前都會觸發,根據from和to來判斷是哪一個路由觸發)

const router = new VueRouter({ ... })

router.beforeEach((to, from, next) => {
  // ...
})

//每一個守衛功能都有三個參數:
//to: Route:導航到的目標Route對象
//from: Route:當前路線被導航離開
//next: Function:必須調用此函數來解析鉤子
//    next():繼續前進到管道中的下一個鉤子。若是沒有留下掛鉤,則確認導航。

//    next(false):停止當前導航。若是瀏覽器URL已更改(由用戶手動或經過後退按鈕),則會將其重置爲from路徑的URL 。

//    next('/')或next({ path: '/' }):重定向到其餘位置。當前導航將停止,並將啓動一個新導航。你能夠經過任何位置對象next,它容許您指定相似的選項replace: true,name: 'home'在使用任何選項router-link的to道具或router.push

//    next(error):(2.4.0+)若是傳遞給的參數next是一個實例Error,導航將被停止,錯誤將傳遞給經過註冊的回調router.onError()。

`

  

    舉個🌰

import Vue from 'vue';
import Router from 'vue-router';
import LoginPage from '@/pages/login';
import HomePage from '@/pages/home';
import GoodsListPage from '@/pages/good-list';
import GoodsDetailPage from '@/pages/good-detail';
import CartPage from '@/pages/cart';
import ProfilePage from '@/pages/profile';

Vue.use(Router)

const router = new Router({
  routes: [
    {
      path: '/',  // 默認進入路由
      redirect: '/home'   //重定向
    },
    {
      path: '/login',
      name: 'login',
      component: LoginPage
    },
    {
      path: '/home',
      name: 'home',
      component: HomePage
    },
    {
      path: '/good-list',
      name: 'good-list',
      component: GoodsListPage
    },
    {
      path: '/good-detail',
      name: 'good-detail',
      component: GoodsDetailPage
    },
    {
      path: '/cart',
      name: 'cart',
      component: CartPage
    },
    {
      path: '/profile',
      name: 'profile',
      component: ProfilePage
    },
    {
      path: '**',   // 錯誤路由
      redirect: '/home'   //重定向
    },
  ]
});

// 全局路由守衛
router.beforeEach((to, from, next) => {
  console.log('navigation-guards');
  // to: Route: 即將要進入的目標 路由對象
  // from: Route: 當前導航正要離開的路由
  // next: Function: 必定要調用該方法來 resolve 這個鉤子。執行效果依賴 next 方法的調用參數。

  const nextRoute = ['home', 'good-list', 'good-detail', 'cart', 'profile'];
  let isLogin = global.isLogin;  // 是否登陸
  // 未登陸狀態;當路由到nextRoute指定頁時,跳轉至login
  if (nextRoute.indexOf(to.name) >= 0) {  
    if (!isLogin) {
      console.log('what fuck');
      router.push({ name: 'login' })
    }
  }
  // 已登陸狀態;當路由到login時,跳轉至home 
  if (to.name === 'login') {
    if (isLogin) {
      router.push({ name: 'home' });
    }
  }
  next();
});

export default router;

 

 

  b、beforeResolve(2.5.0新增)

  全局解析守衛

相似,區別是在導航被確認以前,同時在全部組件內守衛和異步路由組件被解析以後,解析守衛就被調用router.beforeEach

 

  c、afterEach

  全局後置鉤子

router.afterEach((to, from) => {
  // ...
})

//不會接受next函數也
//也不會改變導航自己

 

  d、beforeEnter  

  路由獨享的守衛

const router = new VueRouter({
  routes: [
    {
      path: '/foo',
      component: Foo,
      beforeEnter: (to, from, next) => {
        // ...
      }
    }
  ]
})

//與全局前置守衛的方法參數是同樣的

 

  e、

    組件內的守衛

  • beforeRouteEnter
  • beforeRouteUpdate (2.2新增)
  • beforeRouteLeave
const Foo = {
  template: `...`,
  beforeRouteEnter (to, from, next) {
    // 在渲染該組件的對應路由被 confirm 前調用
    // 不!能!獲取組件實例 `this`
    // 由於當守衛執行前,組件實例還沒被建立
  },
  beforeRouteUpdate (to, from, next) {
    // 在當前路由改變,可是該組件被複用時調用
    // 舉例來講,對於一個帶有動態參數的路徑 /foo/:id,在 /foo/1 和 /foo/2 之間跳轉的時候,
    // 因爲會渲染一樣的 Foo 組件,所以組件實例會被複用。而這個鉤子就會在這個狀況下被調用。
    // 能夠訪問組件實例 `this`
  },

  //離開守衛一般用來禁止用戶在還未保存修改前忽然離開。導航該能夠經過來取消
beforeRouteLeave (to, from, next) {
// 導航離開該組件的對應路由時調用 // 能夠訪問組件實例 `this` } }next(false)

  

//beforeRouteEnter守衛不能訪問this,
//由於守衛在導航確認前被調用,所以即將登場的新組件還沒被建立。

//不過,能夠你傳經過一個回調給next來訪問組件實例。
//在導航被確認的時候執行回調,而且把組件實例做爲回調方法的參數。

beforeRouteEnter (to, from, next) {
  next(vm => {
    // 經過 `vm` 訪問組件實例
  })
}

完整的導航解析流程

  1. 導航被觸發。
  2. 在失活的組件裏調用離開守衛。
  3. 全局調用的beforeEach守衛。
  4. 在重用的組件裏調用beforeRouteUpdate守衛(2.2+)。
  5. 在路由配置裏調用beforeEnter
  6. 解析異步路由組件。
  7. 在被激活的組件裏調用beforeRouteEnter
  8. 調用全局的beforeResolve守衛(2.5+)。
  9. 導航被確認。
  10. 全局調用的afterEach鉤子。
  11. 觸發DOM更新。
  12. 建立³³用實例好的調用beforeRouteEnter守衛中傳給next的回調函數。

  

  

以上。

相關文章
相關標籤/搜索