Vue組件和路由


Vue組件

我們通過將網頁中的內容拆分為小的組件,這些組件可以獨立的完成某些功能,當我們在其他地方需要同樣或者相似功能時候,使用對應的組件即可。組件可以大大的提高我們 代碼的復用率,提高開發效率。

創建組件

在Vue 中,我們可以自己創建組件對象,組件同一個頁面一樣,有自己的html 標簽,自己的 css 樣式,和自己的 js 來處理邏輯。Vue提供了以下的方式來創建組件。

定義組件

定義全局組件是在Vue類上調用extend 和 component方法創建組件(第一種方式),然而 Vue 提供了語法糖,可以不使用 extend 而直接使用一個對象創建(第二種方式)

// 第一種方式,定義組件
<script>
var comp1 = Vue.extend({
    template: "<p> 這是一個組件的html內容 </p>",
  data:function(){
      return {}
  }
})
Vue.compomnet("myComp1", comp1) // myComp1 為組件的名字,直接將該名字的標簽放入放入頁面的元素中即可


// 第二種方式,直接使用一個對象
Vue.compoment("組件名字", { 
      template: "<p> 這是一個組件的html內容 </p>",
        data:function(){ return {} },
    })
</script>

// 按照組件名 使用組件
<div>
    <my-comp1> </my-comp1>   // 名字駝峰命名 需要小寫,並使用 - 分割
</div>

調用 component方法,傳入一個指定的對象來創建組件,這個對象常用的幾個key如下

  • template:一個html 格式的字符串,必須只有一個根元素。同時內部也支持Vue中的插值表達式,各種指令等。
  • data:同Vue 中data 相同,這是組件存放自己數據的地方,但必須是一個function,其返回值會作為組件的data 對象,所以返回值是一個對象。使用data 是函數原因是因為組件可能被多次重復使用,這樣每次使用時,都會調用該函數返回一個自己的 data 對象,不會造成多個標簽的數據相互混亂。(如果不使用函數返回data 而是直接使用data 對象,那么這個組件在被使用多次時候,實際的data 只有一個,每個組件的data 引用同一個 對象,他們的展示的值也是完全相同的,並且,當修改一個組件中的內容,其他組件也會相應的改變,因為他們都是共用的同一個data)
  • methods:定義函數處理自己內部的邏輯。
  • 組件使用 component 方法注冊到Vue對象中后才可以使用。使用時像上述方式直接添加以組件名字相同的標簽即可,或者使用其他標簽,添加一個 is=組件名 的屬性即可,該標簽將會被渲染為這個名字的組件。

抽離template

為了方便編輯,可以將template代碼從對象中抽離出來,使用一個template單獨定義,而后使用選擇器綁定到template上

<template id="app"> 
    <div>
      這是一個組建template內容
  </div>
</template>

<script>
var comp = Vue.extend({
    template:"#app",             //  id選擇器綁定template的內容
    data:function(){
    return {}
  }
})

</script>

組件的組織

一個網頁是由 許許多多的組件組成的,每個區域完成自己的功能,許許多多的組件就需要很好組織他們。從官網的圖示可以很好的理解組件是如何組織的。

組件可以並列使用,也可以嵌套使用,最終形成了這個樣的一棵樹形結構,也就形成了父子組件的關系,同時。

另外,組件還應該能夠被方便的替換,選擇不同的條件時,可以選擇性的在指定的位

父子組件

簡單定義一個父子組件

在一個組件中使用使用另一個組件。

var comp1 = Vue.extend({
  template: "<div> 
          這是父組件
          <my-child > </my-child>
        </div>
", data:function(){ return {} } }) var comp2 = Vue.extend({ template: "<div> 這是子組件 </div>", data:function(){ return {} } }) Vue.component("my-child", comp2) Vue.component("my-parent", comp1)

這里注冊了兩個組件,comp1 中 嵌套了組件comp2,comp1 是 comp2 的父組件,當我們使用父組件時,父組件中的子組件也會被渲染,並屬於父組件的一部分。

使用這種方式,子組件在父組件中使用方式,這個父組件只能渲染這個組件,更優雅的方式是使用動態組件的方式,也就是 is 屬性,該一個標簽添加 is 屬性,這個標簽將會被替換為該名字的組件。

var comp1 = Vue.extend({
      template: "<div> 這是父組件 <p :is='childName'> </p> </div>",
      data: function () {
        return {
          childName:"my-child"
        }
      }
    })

    var comp2 = Vue.extend({
      template: "<div> 這是子組件 </div>",
      data: function () {
        return {}
      },
    })
Vue.component("my-child", comp2)
Vue.component("my-parent", comp1)

這樣通過改變 父組件data中的 childName屬性值該指定子組件的名字,從而渲染指定的組件。

父子組件傳值

在子組件中,無法直接訪問父組件中的任何數據,如果需要使用父組件的數據,需要父組件傳遞給子組件,並且子組件需要在props中指定相同的變量名進行接收。

<parent>
    <child v-bind:parentMsg="msg"></child>
</parent>

var comp2 = Vue.extend({
  template: "<div> 這是子組件 </div>",
  data: function () {
          return {}
    },
  props:["parentMsg"]
  })
Vue.component("my-child", comp2)

msg 是父組件中的變量,通過在子組件標簽中定義一個parentMsg 的屬性接收這個msg的值,在子組件中,props 中定義了一個 parentMsg 的變量名字,這是必須定義的,否則子組件仍然無法使用 標簽中的parentMsg 這個屬性值,並且兩個變量名必須相同,子組件才能夠對應的接收這些傳入的值,所有的傳入的值,都在子組件的 $prosp屬性中,也可以直接使用 this.parentMsg 訪問,這是提供的一種便捷方式。

傳入的數據可以被子組件任意的使用,但是如果傳入的是引用類型的數據,例如數組和對象,子組件最好不要在這個原值上對這個數據或者對象內部數據進行修改,這樣修改會造成父組件中的數據被同步的修改,如果要進行修改,應該進行深拷貝,對副本進行修改。這樣做為了保證數據的單項流動,也就是從父組件向子組件進行傳遞,父組件數據 的更新會向下流動到子組件中,但是反過來則不行。因為子組件接收的父組件的數據可能還被父組件傳遞給了其他的子組件,如果該子組件更改了這個數據,其他子組件的數據也會被更改,而各個子組件應該是相互獨立的,這樣通常會造成意外的結果,並使得數據流動變得難以理解。 

props 驗證

var comp2 = Vue.extend({
  template: "<div> 這是子組件 </div>",
  props:["parentMsg"]
  })
Vue.component("my-child", comp2)

我們定義了子組件可以接收父組件的數據,這個數據會根據變量名進行對應的接收,子組件在接收的同時,是可以在prosp 對數據進行驗證,只需要向下面這樣定義驗證的規則即可。

var comp2 = Vue.extend({
  template: "<div> 這是子組件 </div>",
  props:{
    propA: Number,            // 基礎的類型檢查 (`null` 和 `undefined` 會通過任何類型驗證)
    propB: [String, Number],  // 多個可能的類型
    
    propC: {
      type: String,     // 字符串
      required: true    // 必填
    },
    propD: {
      type: Number,
      default: 100     // 默認為100
    },
    propE: {
      type: Object,
      // 默認值為 對象或數組 都必須從一個工廠函數獲取,原理同data需要 函數返回相同
      default: function () {
        return { message: 'hello' }
      }
    },
    // 自定義驗證函數,返回true 通過,否則驗證失敗
    propF: {
      validator: function (value) {
        // 這個值必須匹配下列字符串中的一個
        return ['success', 'warning', 'danger'].indexOf(value) !== -1
      }
    }
  }
  })

Vue.component("my-child", comp2)

類型檢查可以使用基本的幾種基本數據類型,也可以是自定義的類型,我們可以自定義構造函數,也就是自定義類型,作為type。

為組件定義事件

使用組件時,我們可以為組件綁定自定義的事件,使用 v-on 指令即可

<my-component v-on:my-event="doSomething"></my-component>

這個事件的處理函數是一個dosomething 的函數,這個函數是由組件外部定義的,傳入到組件內部使用,組件內部根據這個 事件名在props 中定義一個同名字符串來接收這個事件。想要調用這個事件則需要 emit 函數進行調用。

例如我們可以將父組件的一個方法傳入子組件中,並在子組件中調用這個方法。

<script>
  // 父組件,定義了一個show函數,並將這個show函數傳遞給子組件
  var comp1 = Vue.extend({
      template: "<parent>
                                    <child v-bind:func="show"></child>  //傳遞show函數,子組件使用func變量接收。
                                </parent>",
      data: function () {
        return {}
      }
      // 父組件中定義的show方法,我們要把他傳遞給子組件,子組件得到后調用他,並可以傳入參數
          methods:{
          show(data){  // 這個函數屬於父組件,子組件通過 $emit()調用時,this是父組件對象而不是子組件
            console.log(data) 
            console.log(this.data)   // 得到了子組件的數據
            this.data = data     
              }
      }
    }) 
  Vue.component("my-parent", comp1)
  
  //  定義一個子組件,並定義一個tocall方法,在方法中調用傳入的函數
  var comp2 = Vue.extend({
  template: "<div> 這是子組件 </div>",
  data: function () {
          return {}
    },
  methods:{
      toCall(){   // 定義一個方法,在這個方法中調用父組件傳入的func 引用的這個函數
        this.$emit("func", "參數1", "參數2")   // 函數名,參數
    }
  }
  props:["func"]      
  })
Vue.component("my-child", comp2)
</script>

子組件使用 func 這個標識符接受了父組件的 show 函數,然后使用 this.$emit()的方式調用這個函數,func 這個標識不會作為變量使用,所以不用遵循變量的定義規則,並且這個標識應該是全小寫,即使在html中使用大寫進行接收,組件內部也只能訪問到全小寫的標識。如果父組件函數有參數,子組件可以將自己的數據作為參數在調用父組件的函數,而這個函數內部的 this 是 父組件對象,這樣父組件對象可以通過獲取參數中的數據,得到子組件中的值,這也是一種子組件向父組件傳值的方式。

組件切換

組件切換也是一種必要的組織組件的方式,我們遇到過登錄注冊功能,登錄時可以切換到注冊組件,反之亦可,在同一個位置上,通過選擇的條件不同,渲染不同的組件。

實現方式

有多種方式實現組件的切換

  • 最low 的方式就是使用 v-if he v-else 條件判斷的方式選擇性渲染。
  • 使用組件的 is 屬性,動態的改變 is 的屬性值來改變組件,上面的例子中已經出現過了,總結以下。
    • 父組件data 中保存當前渲染的 組件名字,頁面中使用 is = 組件名字渲染該組件
    • 改變data 中 當前渲染組件的名字,is 屬性對應的值也相繼改變,從而組件切換
// 點擊按鈕切換,設置不同view值即可
<a href="" @click="view='v-a'"> 切換到a組件</a>
<a href="" @click="view='v-b'"> 切換到b組件</a>

<transition name="component-fade" mode="out-in">
  // 這個標簽,:is 表示顯示該名字得組件
  <component :is="view"></component>
</transition>

var = new Vue({
    data:{
        view:"v-a"
  }
    componments:{
        "v-a":{
            template:"<h1></h1>",
        },
        "v-b":{
            template:"<h1></h1>",
        }
    }
})
  • 最后一種方式則是使用 Vue 中提供的路由。

緩存切換組件

當多個組件進行切換顯示時候,實際上只會單獨的存在一個組件對象,當需要切換到其他的組件時,會立刻創建一個新的組件進行顯示,同時刪除掉當前顯示的組件對象。大多數情況下我們的需求都是這樣的,每次切換獲得全新的組件。但是某些情況我們不希望被切換走的組件被刪除,而是下次可以使用,這就需要將這個組件 進行緩存,緩存后,下次再次展示這個組件時,會使用緩存的組件。默認進行組件切換時不會進行組件緩存,只需要我們指定一個標簽

<keep-alive >
  <component :is="view"></component>
</keep-alive>

當view 變量指定的組件名字改變,將會發生組件切換,而被切換的組件都會被緩存起來。這樣內存中實際上共存着這幾個組件對象,而同一時刻只會有一個組件被渲染。被渲染的組件狀態為 active,而沒有渲染的組件為 deactive,組件的切換會改變組件的 這兩種狀態,組件active 和 deactive 兩種狀態進行切換時候,會觸發兩個生命周期函數,actived 和 deactived 函數,如果需要可以定義這兩個鈎子函數的內容。

使用<keep-alive> 緩存組件時需要注意以下幾點:

  • 在<keep-alive> 內部進行切換組件,每個組件都需要有自己的名字,首先會檢查組件的name 屬性,也支持使用 vue.component("name", comp) 的方式注冊的組件,而不能時沒有注冊的匿名組件。
  • 代碼中的<keep-alive>標簽只是一個緩存的標識,真實的頁面的不會出現在這個標簽。
  • <keep-alive> 內部只可能同時渲染展示一個根組件,其余均為 deactive 狀態。
  • <keep-alive> 下的使用 v-for 展示的內容不會被緩存。
keep-alive的參數

使用 keep-alive 標簽時候,可以添加幾個屬性。

  • include 和 exclude:指定被緩存的組件滿足的條件,例如只想緩存部分組件,或者排除部分組件。可以用逗號分隔字符串、正則表達式或一個數組。匹配的是組建的 name 或者組件局部注冊的名稱,匿名組件不能被匹配。
<!-- 逗號分隔字符串 -->
// 只會緩存 a,b兩個組件,其余組件不會緩存
<keep-alive include="a,b">
  <component :is="view"></component>
</keep-alive>

<!-- 正則表達式 (使用 `v-bind`) -->
<keep-alive :include="/a|b/">
  <component :is="view"></component>
</keep-alive>

<!-- 數組 (使用 `v-bind`) -->
<keep-alive :include="['a', 'b']">
  <component :is="view"></component>
</keep-alive>
  • max:指定緩存的組建的最大數量,一旦這個數字達到了,在新實例被創建之前,已緩存組件中最久沒有被訪問的實例會被銷毀掉。
<keep-alive :max="10">       // 最多緩存10個
  <component :is="view"></component>
</keep-alive>

路由 vue-router

簡介

這里的路由是指前端的路由,也就是通過url 的不同來 選擇性的渲染不同的組件。url 的改變只會讓組件的進行切換,而不是從后端獲取新的頁面。

Vue 的前端路由主要是基於hash 來實現的,也就是url 上 # 標識符之后的部分。例如`http://vue-router/zh/#/user`這樣一個url,#標識符后的路徑為/user,我們可以設置規則匹配這個路徑,使其對應的渲染指定的組件。

導包順序

同樣的,vue-router基於vue對象,所以必須在Vue包之后導入,確保當前環境中已經存在Vue對象。

<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>

路由器對象

想要匹配當前選中的url,然后選擇的渲染對應組件,我們需要一個router對象,並指定一個路由器定義匹配的規則,以及路徑和與組件之間的映射關系。

var router = new VueRouter({     // 一個路由對象,內部配置 路徑映射關系
  routes:[
    { path: '/foo', component: Foo },    // path 指定路徑,component指定對應的組件的對象。
    { path: '/bar', component: Bar }
    ]
})

// 定義好路由器后,還需要將其與對應的Vue對象進行綁定,Vue中的配置對象中有對應的router這個key來綁定路由器。
var vm = new Vue({
    el:"#app",
  data:{},
  methods:{
      show(){
        console.log(this.$router)
      console.log(this.$route)
    }
  },
  router: router,     // 綁定到Vue對象上,這個router 只能子 #app 這個節點內部使用。
})

通過向Vue對象注入路由器,我們可以在Vue對象已經路由對象中使用的任何組件內通過 this.$router 訪問路由器對象,獲得內部的配置信息,也可以通過 this.$route 訪問當前匹配到的路由。上面的方法中嘗試去獲取這個路由。

掛載到Vue上的路由器,會自動根據當前url中hash指定的 路徑匹配到對應的組件,並將這個組件用於展示。但是我們並未向vue說明,我們要在哪里展示匹配到的組件,這就需要一個標記,在這個vue管理的 dom 節點中使用一個router-view標簽即可。

<router-view>標簽

可以直接在頁面中添加<router-view> 標簽,vue 解析該標簽時,會在自己對象上找到路由器對象,根據當前的url 匹配到組件,然后把這個組件渲染到這個標簽的位置,這就是 <router-view> 標簽的作用。

<div id="app">
    <p> 這是app </p>
  <router-view> </router-view>      // 當前url 匹配到的組件將展示到這個位置
    <router-view> </router-view>      // 又有一個該標簽,則會展示一次,兩個組件完全一樣
</div>

<script>
var router = new VueRouter({     // 一個路由對象,內部配置 路徑映射關系
  routes:[
    { path: '/foo', component: Foo },    
    { path: '/bar', component: Bar }
    ]
})

var vm = new Vue({
    el:"#app",
  data:{},
  methods:{},
  router: router,     // 綁定到Vue對象上,這個router 只能子 #app 這個節點內部使用。
})
</script>

在html 中凡是有 <router-view> 標簽的地方,都會使用vue 對象中綁定的路由器匹配到的組件進行填充,所以上面使用了兩次router-view,則會顯示兩個 匹配到的組件。

命名組件

實際上,一個路徑可以匹配到的組件可以不止一個,可以有很多個,當匹配到多個組件時需要對每一個組件命名進行區分,使用時按照組件的名字將組件渲染到指定的位置。而用來渲染的組件的 router-view 組件也有對應的 name 屬性來指定該標簽只會渲染該名字的組件。

<div id="app">
    <p> 這是app </p>
  <router-view > </router-view>           // 沒有指定name屬性,渲染名字為default的組件 
    <router-view name="a"> </router-view>   // 根據name 屬性,查看當前被匹配的所有的組件中是否有 name為 "a"的組件,有則渲染
    <router-view name="b"> </router-view>      
</div>

<script>
var router = new VueRouter({     // 一個路由對象,內部配置 路徑映射關系
  routes:[
    { path: '/foo', components: {   // 匹配到多個組件
        default: comp1,    //  key為組件在 路由中的名字,會對應 router-view 中的name屬性進行匹配
        a: comp2,
        b: comp3,
      }
    }, 
    { path: '/bar', components: {} },
    ]
})

var vm = new Vue({
    el:"#app",
  data:{},
  methods:{},
  router: router,  
})
</script>

嵌套路由

/user/profile                         /user/posts
+------------------+                  +-----------------+
| User             |                  | User            |
| +--------------+ |                  | +-------------+ |
| | Profile      | |  +------------>  | | Posts       | |
| |              | |                  | |             | |
| +--------------+ |                  | +-------------+ |
+------------------+                  +-----------------+

官方的展示很形象,當訪問/user/ 前綴時,會渲染這個user 的組件,而在user組件內部,有一個小的組件,這個組件的內容由 /user/之后的路勁進行匹配,渲染匹配到的子組件。vue 使用了嵌套路由的方式實現這樣的功能。

<div id="app">
  <router-view></router-view>  // 外層用於放置 user 這一層組件的位置。內層組件的坑顯然應該在外層組價(也就是user組件)內部定義
</div>


<script>
  var comp = Vue.component("comp", {
      template:"<div>  <router-view> </router-view>  <div>"   //  comp 組件內部 渲染渲染組件。
  })
  
  var router = new VueRouter({     // 一個路由對象,內部配置 路徑映射關系
    routes:[
      { path: '/user', component:comp,   // 當匹配到/user,會將comp 渲染到 #app 中的router-view位置。
          children: [
        {
          path: 'profile',       // 繼續匹配到profile,也就是/user/profile時,會將UserProfile 渲染到 comp 中的router-view
          component: UserProfile
        },
        {
          path: 'profile', 
          component: UserProfile
        },
      }, 
        ]
    })
  
    var vm = Vue({
    var vm = new Vue({
    el:"#app",
  data:{},
  methods:{},
  router: router,  
})
  })
</script>

通過指定 children屬性的方式,可以再定義一層路由的匹配規則,這些規則匹配到的組件會再其父組件的router-view中渲染,路由的嵌套,也是組件的嵌套。

children 屬性的配置就是像 routes 配置一樣的路由配置數組,結構是相同的,可以再children中再定義children,實現多層的嵌套,同時children中的每一個路由項目,也是可以映射多個組件,並使用命名組件的。

注意:子路由規則前面不要使用"/",使用后將會按照從url的根開始匹配,而不是從父路由匹配結束位置繼續匹配。

定義路由的規則及參數

動態匹配參數

上面的路由是使用字符串的形式完全匹配的,但是有時候url中的路徑是一些變化的值, 例如用戶/user/id這種url

/user/1
/user/2
/user/3

上面的url都應該指向同一個組件對象,當時組件對象又應該獲取他們不同id值。vue提供了這種動態路由匹配的方式。我們如此定義路由即可

var router = new VueRouter({     // 一個路由對象,內部配置 路徑映射關系
    routes:[
      { path: '/user/:id ', component:comp},  //  匹配 /user/ 前綴的,后面部分的值由id接收
        ]
    })

:id 會進行動態的匹配任意值,接收的值會放入一個params對象中,而這個值的key就是id。當我們訪問 /user/1 這個url時候,將會展示comp這個組件,並且在這個組件的內部,我們可以查看其router.params屬性,可以得到一個 {"id":"1"}這樣的對象,id的值會隨着匹配到的url中的值改變,這樣就實現動態路由。:id 這樣的匹配方式會以 / 為邊際,不會匹配超過 / 邊界的內容。例如 /user/1/profile 的 id 匹配到 1 而不會是 1/profile。如果要匹配多個可以使用多個這樣的動態參數,路由規則可可以定義為 /user/:id/:foo ,這樣匹配 /user/1/profile的結果則是, $route.params = { id:"1", foo:"profile"} 

路由參數

url 中可以使用查詢字符串的方式,查詢字符串不會影響 路由的匹配,只是在匹配后向組件添加了一些參數(/user/?id=1&name=tom 和 /user/ 在匹配時的表現是相同的),這些參數可以在組件this.$route.query對象中查看。

例如訪問的url的hash為: /user/?id=1&name=tom

var router = new VueRouter({    
    routes:[
      { path: '/user', component:comp},  // 匹配規則
        ]
    })

通過上面的url訪問,我們可以在路由的query中得到這樣的值, this.$route.query => { "id": "1", name: "tom" } ,無論是使用動態路由,訪問$route.params 對象還是使用 查詢字符串,訪問$route.query 對象,都可以實現url 對組件內部傳值的的功能。

匹配規則中還可以使用通配符來匹配路徑

{ path: '*'}         // 會匹配所有路徑
{ path: '/user-*'}   // 會匹配以 `/user-` 開頭的任意路徑

這樣的匹配規則通常用來捕捉url的錯誤,當上面所有路由都沒有匹配到時,將會匹配到該項。

重定向和別名

// 重定向,訪問/a 時,將用戶訪問重新定位到訪問 '/b' 上,有一個重定向的過程
const router = new VueRouter({
  routes: [
    { path: '/a', redirect: '/b' }   // url匹配到/a 路徑,會重定向到 /b
    { path: '/c', redirect: from => { return '/b'}  }   // from 參數為'/c', return 值為重定向的路徑。
    { path: '/b', redirect: comp}
  ]
})

// 別名:訪問 "/b" 只是/a 的一個別名,兩個規則都指向同一個組件,所以訪問兩個url 都想過都相同,不會發生重定向。
const router = new VueRouter({
  routes: [
    { path: '/a', component: A, alias: '/b' }
  ]
})

導航

定義好了路由對象和對應的匹配規則,我們還需要能快速跳轉到這些 url的方式,vue使用了 router-link標簽來 是西安導航鏈接,這些導航鏈接標簽會被默認渲染為 一個 <a> 標簽。可以通過tag屬性指定 渲染的標簽名。當然也可以使用<a>標簽,注意使用時 href屬性的指定的路徑應該是hash值中的路徑,也就是 <a href="#/user/profile"> </a> ,而不是直接跳轉url中的路徑,所以 應該帶上 # 。

使用router-link的原因主要時更加的方便和靈活,例如可以向<a>標簽那樣指定跳轉路徑

<router-link to="/user" tag="button"> 用戶模塊 </router-link>   //  to 指定跳轉的路徑, tag指定渲染為一個button按鈕
<router-link to="/user/123" tag="button"> 用戶模塊 </router-link>
<router-link to="/user/?id=123" tag="button"> 用戶模塊 </router-link>

可以使用命名路由的名字,並攜帶參數。使用這種方式需要我們為每一個路由項添加一個name屬性

const router = new VueRouter({
  routes: [
    {
      path: '/user/:userId',
      name: 'a',             //  該路由項的name 為 a,所以跳轉時候,只需要指定該名即可指向這條路由
      component: User
    }
  ]
})

<router-link :to="{ name: 'a', params: { userId: 123 }}"  tag="button"> 用戶模塊 </router-link>
// 指定跳轉到 路由項目為 name 為a 的這條路由上,並通過params: { userId: 123 }注入參數,還可以使用query:{"id":123} 注入數據
// to 指定的一個對象,這里需要對 to 進行屬性綁定,也就是 v-bind, to 的值才不會被解析為一個字符串。

代碼中實現url的跳轉

在router-link中,我們可以指定 一個跳轉地址,當點擊該標簽,當前url將會改變,從而頁面發生改變或者刷新,這是通過頁面點擊的方式,點擊標簽能夠跳轉實際上也是通過點擊事件向 一個history 棧 中添加新的記錄實現的。當頁面加載后,vue中會生成一個頁面跳轉的棧信息,棧中最新的元素也就當前頁面的信息,當我們需要展示新的頁面時,將最新的內容push 到這個 history 中,由於棧的最新元素發生了改變,所以頁面跳轉了,同理,如果點擊瀏覽器的后退按鈕,將會從這個history 棧中 pop 最新的元素,所以頁面 會回到上一個操作的頁面。

所以如果我們想要在代碼中實現頁面的跳轉,push 最新的頁面內容即可,vue 為我們做好了 封裝,push 的對象 同router-link中使用的對象即可。例如

// 有這樣一個路由器,內部只定義了一條路由規則
const router = new VueRouter({
  routes: [
    {
      path: '/user/:userId',
      name: 'a',  
      component: User
    }
  ]
})

var vm = new Vue({
  el:"#app",
  data: {},
  router:router,
  methods:{
      optHistory(){
      // 調用router中的push方法,將新的元素也就是router-link 中的 to 屬性的值,添加到history的最新頁面中即可。
      // router內部會解析並找到對應的路由信息。
      this.$router.push('user/123')
      this.$router.push({path:"'/user/123'"})
        this.$router.push({ name:"a", params: { userId: 123 }})  // 向history 中添加新的路由信息,跳轉到新的頁面
    }
  }
})

// 這是一個點擊調轉的按鈕,如果點擊,將會根據 路由項 的name,匹配到上面那一條路由,頁面發生跳轉。
<router-link :to="{ name: 'a', params: { userId: 123 }}"  tag="button"> 用戶模塊 </router-link>

// 我們已經知道了頁面跳轉實際上是history棧中添加了新的元素,而history 棧由router內部,所以,我們可以調用上面method 中的
// optHistory方法,也可以實現點擊跳轉按鈕的功能。

除了push 方法,還可以調用replace(),將最新的記錄替換,而不是進行添加。同樣的我們也可以訪問棧中原來的元素實現頁面回退

router.go(-1)   // 回退一個記錄
 
router.go(1)    // 前進一個記錄
router.go(-3)   // 回退三個記錄

總結路由的使用

這是路由器的基本使用形式,主要包括幾個步驟

  • 創建路由器並在內部建立路徑和組件的映射關系, 嵌套路由使用children指定,匹配路徑時可以使用 ":username" 的動態匹配方式。
  • 路由對象創建完成后,將這個路由器掛載到 vue 對象上,vue對象即可使用。
  • 在這個view對象管理的區域使用 <router-view> 標簽指定一個渲染組件的位置,這個vue對象會將根據當前路徑匹配到的組件渲染到這個位置,如果時嵌套路由,子路由匹配的組件應該在父路由對應的組件中定義。
  • 頁面中使用 router-link 標簽實現url 的改變,類似於<a>標簽,但使用更靈活

每次url 發生改變,路由器就會匹配當前路徑,得到一個組件進行渲染。


免責聲明!

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



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