vue-router

VueRouter--路由

????這里的路由是SPA(單頁應(yīng)用)的路徑管理器。再通俗的說,vue-router就是WebApp的鏈接路徑管理系統(tǒng)。

????vue-router是Vue.js官方的路由插件,它和vue.js是深度集成的,適合用于構(gòu)建單頁面應(yīng)用。vue的單頁面應(yīng)用是基于路由和組件的,路由用于設(shè)定訪問路徑,并將路徑和組件映射起來。傳統(tǒng)的頁面應(yīng)用,是用一些超鏈接來實現(xiàn)頁面切換和跳轉(zhuǎn)的。在vue-router單頁面應(yīng)用中,則是路徑之間的切換,也就是組件的切換。路由模塊的本質(zhì) 就是建立起url和頁面之間的映射關(guān)系。

????至于為什么不能用a標(biāo)簽?這是因為用Vue做的都是單頁應(yīng)用(當(dāng)你的項目準(zhǔn)備打包時,運(yùn)行npm run build時,就會生成dist文件夾,這里面只有靜態(tài)資源和一個index.html頁面),所以你寫的<a></a>標(biāo)簽是不起作用的,你必須使用vue-router來進(jìn)行管理。


一、vue-router實現(xiàn)原理:

????SPA(single page application):單一頁面應(yīng)用程序,只有一個完整的頁面;它在加載頁面時,不會加載整個頁面,而是只更新某個指定的容器中內(nèi)容。單頁面應(yīng)用(SPA)的核心之一是: 更新視圖而不重新請求頁面;vue-router在實現(xiàn)單頁面前端路由時,提供了兩種方式:Hash模式和History模式;根據(jù)mode參數(shù)(mode:'hash')來決定采用哪一種方式。

1、Hash模式:

????vue-router 默認(rèn) hash 模式 —— 使用 URL 的 hash 來模擬一個完整的 URL,于是當(dāng) URL 改變時,頁面不會重新加載。 hash(#)是URL 的錨點,代表的是網(wǎng)頁中的一個位置,單單改變#后的部分,瀏覽器只會滾動到相應(yīng)位置,不會重新加載網(wǎng)頁,也就是說hash 出現(xiàn)在 URL 中,但不會被包含在 http 請求中,對后端完全沒有影響,因此改變 hash 不會重新加載頁面;同時每一次改變#后的部分,都會在瀏覽器的訪問歷史中增加一個記錄,使用”后退”按鈕,就可以回到上一個位置;所以說Hash模式通過錨點值的改變,根據(jù)不同的值,渲染指定DOM位置的不同數(shù)據(jù)。hash 模式的原理是 onhashchange 事件(監(jiān)測hash值變化),可以在 window 對象上監(jiān)聽這個事件。

1、Histoey模式:

????由于hash模式會在url中自帶#,如果不想要很丑的 hash,我們可以用路由的 history 模式,只需要在配置路由規(guī)則時,加入"mode: 'history'",這種模式充分利用了html5 history interface 中新增的 pushState() 和 replaceState() 方法。這兩個方法應(yīng)用于瀏覽器記錄棧,在當(dāng)前已有的 back、forward、go 基礎(chǔ)之上,它們提供了對歷史記錄修改的功能。只是當(dāng)它們執(zhí)行修改時,雖然改變了當(dāng)前的 URL ,但瀏覽器不會立即向后端發(fā)送請求。

????當(dāng)你使用 history 模式時,URL 就像正常的 url,例如 http://yoursite.com/user/id,比較好看!
不過這種模式要玩好,還需要后臺配置支持。因為我們的應(yīng)用是個單頁客戶端應(yīng)用,如果后臺沒有正確的配置,當(dāng)用戶在瀏覽器直接訪問 http://oursite.com/user/id 就會返回 404,這就不好看了。
所以呢,你要在服務(wù)端增加一個覆蓋所有情況的候選資源:如果 URL 匹配不到任何靜態(tài)資源,則應(yīng)該返回同一個 index.html 頁面,這個頁面就是你 app 依賴的頁面。

    {path: "*", redirect: "/"}]
    //此處就設(shè)置如果URL輸入錯誤或者是URL 匹配不到任何靜態(tài)資源,就自動跳到到Home頁面

二、vue-router使用

1、安裝路由

npm istall vue-router --save

2、在src/router/inde.js文件中引入、使用路由

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

Vue.use(VueRouter)  使用路由

3、在src/main.js文件中引入路由配置文件index.js文件,并將路由對象傳遞給vue實例

import router from './router'  //引入路由配置文件

Vue.use(VueRouter)  使用路由
new Vue({
  el: '#app',
  router,   //傳遞路由對象給vue實例
  render: h => h(App)
})

4、在src/router/inde.js配置路由

import Index from './路徑/Index'    //引入組件
const router = new VueRouter({
    mode:'history',     //history模式,可以去除URL里面的hash符號(#)
    routes:[    //注冊組件路由,
        {
            path:'/',   //path設(shè)置路徑,'/'表示根路徑
            conponent:Index,    //設(shè)置的路徑對應(yīng)的組件名
            name:'index'    //組件引用名
        }
    ]
})

5、在app.vue中留坑<router-view></router-view>,Index.vue的內(nèi)容就會展示到router-view這個容器里面

//app.vue中
<template>
    <div>
        <!-- 留坑,非常重要 -->
        <router-view></router-view>
    </div>
</template>

三、路由跳轉(zhuǎn)

[一]、<router-link>基本屬性

    <router-link to="" tag="">主頁</router-link>
(1)to屬性表示綁定地址。to="/"
(2):to="",綁定動態(tài)路由,與data(){}中的變量進(jìn)行綁定--詳見下文[三]、動態(tài)路由。
    綁定路由表中的name屬性。:to="{name:路由表中name值}"
(3)tag屬性表示以什么標(biāo)簽名顯示,默認(rèn)以a標(biāo)簽顯示;tag=div表示將該標(biāo)簽以div呈現(xiàn)
(4)children:[],子路由在這里面配置,children:[{path:'/',component:xxx,name:xxx,cildren:[三級路由]},....]

[二]、路由跳轉(zhuǎn)

1、跳轉(zhuǎn)到上一次瀏覽的頁面--this.$router.go(-1);

<template>
  <div class="container">
    <h1>home</h1>
    <button @click="goToMenu" class="btn btn-success">just do it</button>
  </div>
</template>

<script>
export default {
  name: "Home",
  methods:{
    goToMenu(){
      //跳轉(zhuǎn)到上一次瀏覽的頁面
      this.$router.go(-1);
    }
  }
}
</script>

2、跳轉(zhuǎn)到指定的頁面--this.$router.replace('/about')

<template>
  <div class="container">
    <h1>home</h1>
    <button @click="goToMenu" class="btn btn-success">just do it</button>
  </div>
</template>

<script>
export default {
  name: "Home",
  methods:{
    goToMenu(){
      //指定跳轉(zhuǎn)
      this.$router.replace('/about')
    }
  }
}
</script>

3、跳轉(zhuǎn)到指定路由的名字下--this.$router.replace({name:'nameValue'})

在router/index.js文件下,對Menu.vue組件進(jìn)行name賦值

  {
    path:'/menu',
    component:Menu,
    name:'menuLink'
  },

在Home.vue文件中

<template>
  <div class="container">
    <h1>home</h1>
    <button @click="goToMenu" class="btn btn-success">just do it</button>
  </div>
</template>

<script>
export default {
  name: "Home",
  methods:{
    goToMenu(){
      //跳轉(zhuǎn)到指定路由的名字
      this.$router.replace({name:'menuLink'})
    }
  }
}
</script>

4、通過this.$router.push()地址,或者name進(jìn)行跳轉(zhuǎn)

  • 開發(fā)中這種方法最常用
<template>
  <div class="container">
    <h1>home</h1>
    <button @click="goToMenu" class="btn btn-success">just do it</button>
  </div>
</template>

<script>
export default {
  name: "Home",
  methods:{
    goToMenu(){
      //push地址跳轉(zhuǎn)
      this.$router.push('/menu')
      //或者是通過name屬性
      //this.$router.push({name:'menuLink'})
    }
  }
}
</script>

[三]、動態(tài)路由

動態(tài)路由是將:to屬性的值設(shè)置為data中的變量(:to="routerDemo"),將具體的路由地址賦值給變量
<li><router-link :to="homeLink">主頁</router-link></li>
export default {
  name: "Header",
  data(){
    return{
      homeLink:'/'
    }
  }
}
</script>

[四]、以導(dǎo)航欄的實現(xiàn)來理解

此導(dǎo)航欄只使用了bootstrapcss樣式,在index.html中插入

    <link  rel="stylesheet" integrity="sha384-B0vP5xmATw1+K9KRQjQERJvTumQW0nPEzvF6L/Z6nronJ3oUOFUFpCjEUQouq2+l" crossorigin="anonymous">

1、創(chuàng)建主頁(Home)、菜單(OrderingGuide)、管理(Admin)、關(guān)于我們(about/About)、登錄(Login)、注冊(Register)組件

<!-- home組件,其余組件略過-->
<template>
  <h1>home</h1>
</template>

<script>
export default {
  name: "Home"
}
</script>

2、在src/router/index.js中配置路由

import Home from './components/Home'
import Menu from './components/Menu'
import Admin from './components/Admin'
import About from './components/about/About'
import Login from './components/Login'
import Register from './components/Register'
const router = new VueRouter({
    mode:'history',     //history模式,可以去除URL里面的hash符號(#)
    routes:[    //注冊組件路由,
             {
                    path:'/',
                    component:Home,
                 },{
                    path:'/menu',
                    component:Menu
                },{
                    path:'/admin',
                    component:Admin
                },{
                    path:'/about',
                    component:About,
                 },{
                    path:'/login',
                    component:Login
                },{
                    path:'/register',
                    component:Register
                 }
            ]
})

3、新建一個header.vue組件,用于寫頂部導(dǎo)航欄

<template>
  <header>
    <nav class="navbar navbar-expand-lg navbar-light bg-light">
<!--      svg矢量圖logo-->
      <a class="py-2" href="#" aria-label="Product">
        <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" class="d-block mx-auto" role="img" viewBox="0 0 24 24" focusable="false"><title>Product</title><circle cx="12" cy="12" r="10"></circle><path d="M14.31 8l5.74 9.94M9.69 8h11.48M7.38 12l5.74-9.94M9.69 16L3.95 6.06M14.31 16H2.83m13.79-4l-5.74 9.94"></path></svg>
      </a>
      <a href="/" class="navbar-brand">Pizza點餐系統(tǒng)</a>
<!--      頂部  左側(cè)-->
      <ul class="navbar-nav">
<!--        navbar-nav去除li前面的小點-->
        <li><router-link to="/" class="nav-link">主頁</router-link></li>
        <li><router-link to="/menu" class="nav-link">菜單</router-link></li>
        <li><router-link to="/admin" class="nav-link">管理</router-link></li>
        <li><router-link to="/about" class="nav-link">關(guān)于我們</router-link></li>
      </ul>
      <!--        頂部-右側(cè)-->
      <ul class="navbar-nav ml-auto">
<!--        ml-auto實現(xiàn)兩個li在頂部最右側(cè)-->
        <li><router-link to="/login" class="nav-link">登錄</router-link></li>
        <li><router-link to="/register" class="nav-link">注冊</router-link></li>
      </ul>
    </nav>
  </header>
</template>

<script>
export default {
  name: "Header"
}
</script>

4、在app.vue中引入導(dǎo)航欄,以及為導(dǎo)航欄的導(dǎo)航組件(主頁、菜單、管理等)留坑

<template>
  <div id="app">
      <!-- header導(dǎo)航欄組件將在這展示-->
    <div class="container">
      <app-header></app-header>
    </div>
   <!--   為導(dǎo)航欄的導(dǎo)航組件(主頁、菜單、管理等)留坑-->
    <div class="container">
      <router-view></router-view>
    </div>
  </div>
</template>

<script>
import Header from "./components/Header";
export default {
  name: 'app',
  components:{
    //屬性名:組件名
    //屬性名駝峰式命名的話 ,ES6會自動解析為app-header;如果屬性名命名為app-header的話,必須使用引號
    appHeader:Header,
  }
}
</script>

[五]、路由嵌套

1、在router/index.js文件中配置一級、二級、三級路由

//一級路由
import About from './components/about/About'

//二級路由
import Contact from "./components/about/Contact";
import Delivery from "./components/about/Delivery";
import History from "./components/about/History";
import OrderingGuide from "./components/about/OrderingGuide";

//三級路由
import Person from "./components/about/contact/Person";
import Phone from "./components/about/contact/Phone";
  {
    path:'/about',
    component:About,
    name:'aboutLink',
    redirect:'/about/history',//默認(rèn)顯示
    children:[
      {
        path:'/about/contact',
        name:'contactLink',
        component:Contact,
        children:[
          {
            path:'/phone',
            name:'phoneNumber',
            component:Phone
          },{
            path:'/person',
            name:'person',
            component:Person
          },
        ]
      },{
        path:'/about/delivery',
        name:'deliveryLink',
        component:Delivery
      },{
        path:'/about/history',
        name:'historyLink',
        component:History
      },{
        path:'/about/orderingGuide',
        name:'orderingGuideLink',
        component:OrderingGuide
      },
    ]
  },

2、一級路由的vue文件

導(dǎo)航欄header組件在app.vue中使用

<template>
  <div id="app">
    <div class="container">
    <!--使用header組件-->
      <app-header></app-header>
    </div>
    <div class="container">
  <!--header上的每一個按鈕對應(yīng)的vue文件內(nèi)容將展示在此-->  
      <router-view></router-view>
    </div>
  </div>
</template>

<script>
import Header from "./components/Header";
export default {
  name: 'app',
  components:{
    //屬性名:組件名
    //屬性名駝峰式命名的話 ,ES6會自動解析為app-header;如果屬性名命名為app-header的話,必須使用引號
    appHeader:Header,//引用header組件
  },
}
</script>

header組件內(nèi)容

<template>
  <header>
    <nav class="navbar navbar-expand-lg navbar-light bg-light">
<!--      頂部  左側(cè)-->
      <ul class="navbar-nav">
<!--        navbar-nav去除li前面的小點-->
        <li><router-link to="/about" class="nav-link">關(guān)于我們</router-link></li>
      </ul>
      <!--        頂部-右側(cè)-->
    </nav>
  </header>
</template>

3、二級路由的vue文件

<template>
  <div>
    <div class="row mb-5">
      <div class="col-4">
        <!--        導(dǎo)航router-link-->
        <div class="list-group mb-5">
          <router-link tag="li" class="nav-link" :to="{name:'historyLink'}">
            <a class="list-group-item list-group-item-action">歷史訂單</a>
          </router-link>
          <router-link tag="li" class="nav-link" :to="{name:'contactLink'}">
            <a class="list-group-item list-group-item-action">聯(lián)系我們</a>
          </router-link>
          <router-link tag="li" class="nav-link" :to="{name:'orderingGuideLink'}">
            <a class="list-group-item list-group-item-action">點餐</a>
          </router-link>
          <router-link tag="li" class="nav-link" :to="{name:'deliveryLink'}">
            <a class="list-group-item list-group-item-action">快遞信息</a>
          </router-link>
        </div>
      </div>
      <div class="col-8">
<!--  留坑,三級路由的vue文件內(nèi)容將展示在此。about路由下的兩個子路由內(nèi)容,點擊后將展示在此-->
        <router-view></router-view>
      </div>
    </div>
  </div>
</template>

[六]、router-view復(fù)用,通過路由的方式重復(fù)使用同一個組件

1、在需要復(fù)用的路由下添加conponents屬性

//src/router/index.js
  {
    path:'/',
    component:Home,
    name:'homeLink',
    components:{    //需要復(fù)用的組件
      'orderingGuide':OrderingGuide,
      'delivery':Delivery,
      'history':History
    }
  },

2、在需要復(fù)用組件的vue文件使用router-view-----未完待續(xù)

<!--    router-view復(fù)用-->
    <div class="container">
      <div class="row">
        <div class="col-sm-12 col-md-4">
          <router-view name="orderingGuide"></router-view>
        </div>
        <div class="col-sm-12 col-md-4">
          <router-view name="delivery"></router-view>
        </div>
        <div class="col-sm-12 col-md-4">
          <router-view name="history"></router-view>
        </div>
      </div>
    </div>
  </div>

四、路由守衛(wèi)

1、全局守衛(wèi)

    router.beforeEach((to,from,next)=>{
    to:路由地址,即將要進(jìn)入的目標(biāo) 路由對象
    from:路由地址,從哪一個路由離開
    next:異步函數(shù),決定展示頁面 
    })
// 全局守衛(wèi)
router.beforeEach((to,from,next)=>{
comsole.log(to);
//這里通常是判斷store.getters.isLogin===false來確定是否登錄
  if(to.path == '/login' || to.path == '/register'){
    next();
  }else{
    alert('未登錄')
    next('/login')
  }
})

2、全局后置鉤子

    router.afterEach((to,from)=>{
    to:路由地址,即將要進(jìn)入的目標(biāo) 路由對象
    from:路由地址,從哪一個路由離開
    })

3、路由獨(dú)享守衛(wèi)

beforeEnter:(to,from,next)=>{
//寫在路由配置里面
}
  {
    path:'/admin',
    component:Admin,
    name:'adminLink',
    beforeEnter:(to,from,next)=>{
      alert('非管理員禁止進(jìn)入');
        if(to.path == '/login' || to.path == '/register'){
    next();
  }else{
    alert('未登錄')
    next('/login')
  }
    }
  },

4、組件內(nèi)的守衛(wèi)

  beforeRouteEnter (to, from, next) {
    // 在渲染該組件的對應(yīng)路由被 confirm 前調(diào)用
    // 不!能!獲取組件實例 `this`
    // 因為當(dāng)守衛(wèi)執(zhí)行前,組件實例還沒被創(chuàng)建
  },
  beforeRouteUpdate (to, from, next) {
    // 在當(dāng)前路由改變,但是該組件被復(fù)用時調(diào)用
    // 舉例來說,對于一個帶有動態(tài)參數(shù)的路徑 /foo/:id,在 /foo/1 和 /foo/2 之間跳轉(zhuǎn)的時候,
    // 由于會渲染同樣的 Foo 組件,因此組件實例會被復(fù)用。而這個鉤子就會在這個情況下被調(diào)用。
    // 可以訪問組件實例 `this`
  },
  beforeRouteLeave (to, from, next) {
    // 導(dǎo)航離開該組件的對應(yīng)路由時調(diào)用
    // 可以訪問組件實例 `this`
  }

(1)、beforeRouteEnter

  beforeRouteEnter(to,from,next){
    //會報錯,Cannot read property 'name' of undefined
    alert('查看現(xiàn)在能否拿到data內(nèi)的數(shù)據(jù)'+this.name);
  }

????beforeRouteEnter 守衛(wèi) 不能 訪問 this,因為守衛(wèi)在導(dǎo)航確認(rèn)前被調(diào)用,因此即將登場的新組件還沒被創(chuàng)建。

????不過,你可以通過傳一個回調(diào)給 next來訪問組件實例。在導(dǎo)航被確認(rèn)的時候執(zhí)行回調(diào),并且把組件實例作為回調(diào)方法的參數(shù)。

beforeRouteEnter (to, from, next) {
  next(vm => {
    // 通過 `vm` 訪問組件實例
     alert('查看現(xiàn)在能否拿到data內(nèi)的數(shù)據(jù)'+vm.name);
  })
}

(2)、beforeRouteUpdate

待續(xù).....

(3)、beforeRouteLeave

  beforeRouteLeave(to,from,next){
    alert('查看現(xiàn)在能否拿到data內(nèi)的數(shù)據(jù)'+this.name)
    if(confirm('確定離開嗎???') == true){
      next()
    }else{
      next(false)
    }
  }
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容