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


react router @4 和 vue路由

本文大綱:

1、vue路由基礎和使用

2、react-router @4用法

3、什么是包容性路由?什么是排他性路由?

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

5、react如何在路由里面定義一個子路由?

6、vue如何在路由里面定義一個子路由?

7、react怎么通過路由傳參?

8、vue怎么通過路由傳參?

9、怎么在react里拿到router對象?

10、怎么在vue里拿到router對象?

11、路由怎么回退?

12、react路由守衛?

13、vue路由守衛?

 


 

1、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

 


 

2、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))

 

 


 

 

3、什么是包容性路由?什么是排他性路由?

  

  包容性路由:

    如果路由有/food 和 /food/1 那么在匹配 /food 的時候兩個都能匹配到

    react就是典型的包容性路由

    所以react需要引入Switch標簽,把路由變成排他性的

  

  排他性路由: 

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

    vue是排他性路由

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

 


 

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

  a、Route 可以寫行間render,render={()=>{return }}
 
  b、也可以寫行間children={()={return }}
 
  c、不管匹配與否children都執行
 
  d、render優先級比children高

  


 
5、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子路由

 


 

 

6、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

 


 

7、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" 

 


 

8、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

 


 

 

9、怎么在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))

 


 

 

10、怎么在vue里拿到router對象? 

//在使用的時候

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

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

 


 

11、路由怎么回退?

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

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

 


 

 

12、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
    

 

13、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`
  },

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

  

//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的回調函數。

  

  

以上。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM