5、Vue 路由

一、URL中的#號

1、簡介

在單頁面應用程序 (SPA - single page application) 中,URL中一般都會包含#。

井號#(Hash): 位置標識符, 代表網頁中的一個位置,用於前端的URL中(注意:井號#只用於前端URL中不能在HTTP請求中使用,#是用來讓瀏覽器滾動的,對服務器端完全無用),其右面的字符就是該位置的標識符。比如http://www.example.com/index.html#location1就代表index.html中的location1位置。瀏覽器讀取這個URL後,會自動將location1位置滾動至可視區域。在第一個#後面出現的任何字符,都會被瀏覽器解讀爲位置標識符。

爲網頁位置指定標識符,有兩個方法:

  • 一是使用錨點,比如
  • 二是使用id屬性,比如
2、注意事項
  • 大部分使用的是#號,也有使用”#!"的。
  • 單單改變#後的部分,瀏覽器只會滾動到相應位置,不會重新加載網頁。
  • 每一次改變#後的部分,都會在瀏覽器的訪問歷史中增加一個記錄,使用"後退"按鈕,就可以回到上一個位置。這對於ajax應用程序特別有用,可以用不同的#值,表示不同的訪問狀態,然後向用戶給出可以訪問某個狀態的鏈接。
  • window.location.hash這個屬性可讀可寫。讀取時,可以用來判斷網頁狀態是否改變;寫入時,則會在不重載網頁的前提下,創造一條訪問歷史記錄。
  • 當#值發生變化時,就會觸發onhashchange事件, 可以通過如下三種方式來綁定事件,對於不支持onhashchange的瀏覽器,可以用setInterval監控location.hash的變化。
window.onhashchange = func;
<body onhashchange="func();">
window.addEventListener("hashchange", func, false);
3、示例
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>瀏覽器中的#號作用</title>
</head>
<body onhashchange="hashChange()">
  <div>
    <div style="position:fixed; right: 0px; bottom: 0px; width:100px;">
      <a href="#location1">滾動到位置1</a>
      <button onclick="scrollToLocation('/location2')">滾動到位置2</button>
      <button onclick="scrollToLocation('location3')">滾動到位置3</button>
      <a href="#topLocation">回到頂部</a>
    </div>
  </div>

  <a name="topLocation"></a>

  <div id="location1" style="height: 700px; background-color: beige">
    location1
  </div>

  <div id="/location2" style="height: 700px; background-color: blueviolet">
    location2
  </div>

  <div id="location3" style="height: 700px; background-color: brown">
    location3
  </div>

  <script>
    function hashChange() {
      console.log('位置標識符改變:' + window.location.hash)
    }

    function scrollToLocation(location) {
      window.location.hash = location
    }
  </script>
</body>
</html>

二、vue-router簡介

Vue Router 是 Vue.js 官方的路由管理器。它和 Vue.js 的核心深度集成,讓構建單頁面應用變得易如反掌。包含的功能有:

  • 嵌套的路由/視圖表
  • 模塊化的、基於組件的路由配置
  • 路由參數、查詢、通配符
  • 基於 Vue.js 過渡系統的視圖過渡效果
  • 細粒度的導航控制
  • 帶有自動激活的 CSS class 的鏈接
  • HTML5 歷史模式或 hash 模式,在 IE9 中自動降級
  • 自定義的滾動條行爲

路由:就是“頁面”之間跳轉,因Vue.js是單頁應用(single page application,SPA),即組件之間的切換。

三、 聲明式路由< router-link to="/path" >

路由開發步驟:
  • 開發組件(component)
  • 配置路由(routes)
  • 渲染:路由鏈接(< router-link to="/path">)和路由視圖(< router-view>< /router-view>)
  • 將組件 (component) 映射到路由 (routes),然後告訴 Vue Router哪個鏈接(< router-link to="/path">) 要在哪裏(< router-view>)來渲染它們。
1、開發組件
Foo.vue
<template>
    <div>
      Foo
    </div>
</template>

<script>
  export default {
    name: 'Foo'
  }
</script>

<style scoped>

</style>
Bar.vue

$route.params.路徑變量: 用於獲取路由的路徑變量, 就像Java中的@PathVariable一樣。監聽動態路徑參數的變化可以通過watch: { ‘$route’ (to, from) { } }或者beforeRouteUpdate (to, from, next) { }, 兩者的區別是watch沒有next 參數。

watch: {
  '$route' (to, from) {
    // 對路由變化作出響應...
  }
},
beforeRouteUpdate (to, from, next) {
	next()
}
<template>
    <div>
      Bar {{ this.$route.params.id }}
    </div>
</template>

<script>
  export default {
    name: 'Bar',
    created () {
      this.init()
    },
    beforeRouteUpdate (to, from, next) {
      console.log(to)
      console.log(from)
      console.log(next)
      // 需要調用next()纔會繼續路由,就像攔截器一樣放開攔截
      next()
      this.init()
    },
    methods: {
      init () {
        console.log('Bar created ' + this.$route.params.id)
      }
    }
  }
</script>

<style scoped>

</style>
2、配置路由(src/router/index.js)

關於path,可以使用路徑參數(:參數名)的形式,也可以使用更加複雜的正則表達式。這種稱之爲“動態路由”

使用表達式當匹配到多個路徑時優先匹配第一個滿足條件的路徑。

注意:當多個路徑路由到同一個組件時,因爲組件會被複用,所以此時對於生命週期鉤子只會調用一次。可以通過beforeRouteUpdate函數來監聽路由的變化,在函數體內處理一些邏輯,比如將created的邏輯提取到某個方法中,然後在created和beforeRouteUpdate分別調用該方法。

// 導入vue-router,vue-router需要依賴vue
import Vue from 'vue'
import Router from 'vue-router'

import Foo from '../components/Foo'
import Bar from '../components/Bar'

// 使用vue-router插件
Vue.use(Router)

// 導出Router對象,以便被其它文件(main.js)導入
export default new Router({
  routes: [
    {
      path: '/foo',
      component: Foo
    },
    {
      path: '/bar/:id',
      name: 'bar',
      component: Bar
    }
  ]
})

3、src/main.js
import Vue from 'vue'
import App from './App'
// 導入Router
import router from './router'

/* eslint-disable no-new */
// 引用router
new Vue({
  el: '#app',
  router,
  components: { App },
  template: '<App/>'
})
4、App.vue

使用<router-link to="/path">配置頁面跳轉鏈接,<router-link to="/path">將被解析成<a href="#/path" class="router-link-active">如果路徑匹配成功後還會自動設置class=“router-link-active”

<router-view>用於定義跳轉頁面的模板內容將在哪個地方展示,即跳轉頁面的內容將會把<router-view>標籤替換成具體的模板內容

<template>
  <div id="app">
    Vue Router
    <p>
      <router-link to="/foo">Go to Foo</router-link>
      <router-link to="/bar/1">Go to Bar 1</router-link>
      <router-link :to="{name: 'bar', params: {id: 2}}">Go to Bar 2</router-link>
    </p>
    
    <router-view></router-view>
  </div>
</template>

<script>
  export default {
    name: 'App'
  }
</script>

<style>
  #app {
    font-family: 'Avenir', Helvetica, Arial, sans-serif;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    text-align: center;
    color: #2c3e50;
    margin-top: 60px;
  }
</style>

四、編程式路由this.$router.push(…)

1、this.$router.push(…)

使用<router-link>標籤來切換組件稱之爲聲明式路由。也可以通過編程的方式來調用路由器router的push方法來切換組件, 調用router.push(…)方法會向 history棧添加一個新的記錄,所以當用戶點擊瀏覽器後退按鈕時,則回到之前的URL。實際上聲明式路由內部也會調用router.push(…)方法。

// 添加組件(會將路徑添加到history棧中)
router.push(location, onComplete?, onAbort?)

// 替換組件(不會將路徑添加到history棧中)
router.replace(location, onComplete?, onAbort?)

// 前進或者後退
router.go(n)
  • location : 切換組件的路徑,可以是一個純字符串的路徑,或者是一個路徑對象(可以包含組件名稱name、路徑path、參數params、查詢參數query)。

  • onComplete:可選回調函數,將會在導航成功完成 (在所有的異步鉤子被解析之後)後回調。

  • onAbort:可選回調函數,終止 (導航到相同的路由、或在當前導航完成之前導航到另一個不同的路由)時調用。

// 字符串
router.push('foo')

// 對象
router.push({ path: 'foo' })

// 命名的路由(注意:params不能與path結合使用)
// name:是指都會配置路由時的name值
// 這種方式參數不會追加在路徑後面
router.push({ name: 'user', params: { userId: 123 }})

// 帶查詢參數,變成 /register?plan=private
// 這種方式會將參數追加到路徑後面
router.push({ path: 'register', query: { plan: 'private' }})
  • router.replace跟router.push很像,唯一的不同就是,它不會向 history 添加新記錄,而是跟它的方法名一樣 —— 替換掉當前的 history 記錄。
2、router.go(n)

這個方法的參數是一個整數,意思是在 history 記錄中向前或者後退多少步,類似 window.history.go(n)。

// 在瀏覽器記錄中前進一步,等同於 history.forward()
router.go(1)

// 後退一步記錄,等同於 history.back()
router.go(-1)

// 前進 3 步記錄
router.go(3)

// 如果 history 記錄不夠用,那就默默地失敗唄
router.go(-100)
router.go(100)
3、使用示例
Foo.vue
<template>
    <div>
      Foo
    </div>
</template>

<script>
  export default {
    name: 'Foo'
  }
</script>

<style scoped>

</style>
Bar.vue
<template>
    <div>
      Bar query: {{ this.$route.query }}
    </div>
</template>

<script>
  export default {
    name: 'Bar',
    created () {
      this.init()
    },
    beforeRouteUpdate (to, from, next) {
      console.log(to)
      console.log(from)
      console.log(next)
      // 需要調用next()
      next()
      this.init()
    },
    methods: {
      init () {
        console.log('Bar created ' + this.$route.params.id)
      }
    }
  }
</script>

<style scoped>

</style>
Foobar.vue
<template>
    <div>
      Foobar {{ this.$route.params.id }}
    </div>
</template>

<script>
  export default {
    name: 'Foobar'
  }
</script>

<style scoped>

</style>
src/router/index.js
import Vue from 'vue'
import Router from 'vue-router'

import Foo from '../components/Foo'
import Bar from '../components/Bar'
import Foobar from '../components/Foobar'

Vue.use(Router)

export default new Router({
  routes: [
    {
      path: '/foo',
      component: Foo
    },
    {
      path: '/bar/:id',
      component: Bar
    },
    {
      path: '/foobar',
      name: 'Foobar',
      component: Foobar
    }
  ]
})
App.vue
<template>
  <div id="app">
    Vue Router
    <p>
      <button @click="jumpFoo">字符串foo</button> <br>
      <button @click="$router.push({path: 'foo'})">對象{path: 'foo'}</button> <br>
      <button @click="$router.push({name: 'Foobar', params:{id: 1}})">命名的路由 {name: '', params: {id: 1}}"</button> <br>
      <button @click="$router.push({path: '/bar/666', query:{age: 2}})">帶查詢參數<{path: '', query: {}}</button> <br>

      <button @click="$router.go(-1)">後退一步</button> <br>
    </p>

    <router-view></router-view>
  </div>
</template>

<script>
  export default {
    name: 'App',
    methods: {
      jumpFoo() {
        this.$router.push('foo', function () {
          console.log('onComplete: 跳轉完成')
        }, function (err) {
          console.log('onAbort')
        })
      }
    }
  }
</script>

<style>
  #app {
    font-family: 'Avenir', Helvetica, Arial, sans-serif;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    text-align: center;
    color: #2c3e50;
    margin-top: 60px;
  }
</style>

五、導航守衛

導航守衛(導航的生命週期):用於監聽路由發生變化的各個生命週期。可以在多個地方來監聽路由的變化,如全局的, 單個路由獨享的, 或者組件級的。

  • router.beforeEach(to, from, next) => { }) 全局前置守衛
    • to : Route類型,即將要進入的目標路由對象。
    • from: Route類型,當前導航正要離開的路由對象。
    • next:Function類型,用於決定接下來如何導航,如進行下一個鉤子、 中斷當前導航、跳轉到其它地址等。確保要調用 next 方法,否則鉤子就不會被 resolved。
      next(): 進行管道中的下一個鉤子。如果全部鉤子執行完了,則導航的狀態就是 confirmed (確認的)。
      • next(false): 中斷當前的導航。如果瀏覽器的 URL 改變了 (可能是用戶手動或者瀏覽器後退按鈕),那麼 URL 地址會重置到 from 路由對應的地址。
      • next(’/’) 或者 next({ path: ‘/’ }): 跳轉到一個不同的地址。當前的導航被中斷,然後進行一個新的導航。你可以向 next 傳遞任意位置對象,且允許設置諸如 replace: true、name: ‘home’、redirect 之類的選項以及任何用在 router-link 的 to prop 或 router.push 中的選項。
      • next(error): (2.4.0+) 如果傳入 next 的參數是一個 Error 實例,則導航會被終止且該錯誤會被傳遞給 router.onError() 註冊過的回調。
  • beforeEnter: (to, from, next) => { } 路由獨享的守衛, 配置在路由中
  • beforeRouteEnter(to, from, next) { } 組件內的守衛,在組件內部使用,在渲染該組件的對應路由被 confirm 前調用
  • beforeRouteUpdate (to, from, next) { } 組件內的守衛,在組件內部使用,在當前路由改變,但是該組件被複用時調用,舉例來說,對於一個帶有動態參數的路徑 /foo/:id,在 /foo/1 和 /foo/2 之間跳轉的時候,
  • beforeRouteLeave (to, from, next) { } 組件內的守衛,在組件內部使用,導航離開該組件的對應路由時調用。
完整的導航解析流程:
  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 的回調函數。

使用示例
App.vue
<template>
  <div id="app">
    <button @click="$router.push('/foo')">foo</button> <br>
    <button @click="$router.push('/bar')">bar</button> <br>

    <router-view></router-view>
  </div>
</template>

<script>
  export default {
    name: 'App',
  }
</script>
src/main.js 全局監聽路由變化
// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App'
import router from './router'
import ElementUI from 'element-ui'


Vue.config.productionTip = false

Vue.use(ElementUI)

router.beforeEach((to, from, next) => {
  console.log('全局前置守衛beforeEach')
  console.log(to)
  console.log(from)
  console.log('------------------')
  next()
})

router.afterEach((to, from) => {
  console.log('全局後置鉤子afterEach')
  console.log(to)
  console.log(from)
  console.log('------------------')
})

/* eslint-disable no-new */
new Vue({
  el: '#app',
  router,
  components: { App },
  template: '<App/>'
})
src/router/index.js 單個路由的導航監聽
import Vue from 'vue'
import Router from 'vue-router'

import Foo from '../components/Foo'
import Bar from '../components/Bar'

Vue.use(Router)

export default new Router({
  routes: [
    {
      path: '/foo',
      component: Foo,
      beforeEnter: (to, from, next) => {
        console.log('路由獨享的守衛beforeEnter')
        console.log(to)
        console.log(from)
        console.log('------------------')
        next()
      }
    },
    {
      path: '/bar',
      component: Bar
    }
  ]
})
Foo.vue 組件內部導航路由的監聽
<template>
    <div>
      Foo 路由守衛
    </div>
</template>

<script>
  export default {
    name: 'Foo',
    beforeRouteEnter (to, from, next) {
      console.log('beforeRouteEnter')
      console.log(to)
      console.log(from)
      console.log('------------------')
      next()
    },
    beforeRouteUpdate (to, from, next) {
      console.log('beforeRouteUpdate')
      console.log(to)
      console.log(from)
      console.log('------------------')
      next()
    },
    beforeRouteLeave (to, from, next) {
      const answer = window.confirm('你確定要離開嗎?')
      if (answer) {
        console.log('beforeRouteLeave')
        console.log(to)
        console.log(from)
        console.log('------------------')
        next()
      } else {
        next(false)
      }
    }
  }
</script>
meta(路由元信息)

meta用於配置路由的元數據,可以理解爲爲該路由配置一些靜態參數,然後在獲取到目標路由時獲取這些參數。

比如:爲每個路由配置是否需要登錄才能訪問,有的路由需要登錄,有的路由不需要登錄,可以配置一個全局導航,判斷一下目標路由是否需要登錄,如果需要登錄再檢查是否已經登錄,如果沒有登錄就跳轉到登錄界面,否則跳轉到目標組件。

App.vue

<template>
  <div id="app">
    <button @click="$router.push('/foo')">foo</button> <br>
    <router-view></router-view>
  </div>
</template>

<script>
  export default {
    name: 'App',
  }
</script>

src/router/index.js

import Vue from 'vue'
import Router from 'vue-router'

import Foo from '../components/Foo'
import Login from '../components/Login'

Vue.use(Router)

export default new Router({
  routes: [
    {
      path: '/foo',
      component: Foo,
      meta: { requiresAuth: true }
    },
    {
      path: '/login',
      component: Login
    }
  ]
})

src/main.js

router.beforeEach((to, from, next) => {
  if (to.matched.some(record => record.meta.requiresAuth)) {
    let isNotLogin = true;
    if (isNotLogin) {
      next({
        path: '/login',
        query: { redirect: to.fullPath}
      })
    } else {
      next()
    }
  } else {
    next()
  }
})

六、參數轉屬性

組件在this.$router.push(...)時可以攜帶參數(動態路徑、params、query),我們在目標組件中可以通過{{ this.$route.params.參數名 }}或者{{ this.$route.query }}來獲取參數, 我們也可以將參數轉換成屬性props, 然後直接使用 {{ 參數名 }}來獲取。

props可以爲布爾類型或者函數類型,布爾類型一般用於動態路徑,函數類型更加靈活強大。在配置路由時需要配置props, 在目標組件也要定義出所有可用的props。

App.vue

<template>
  <div id="app">
    <button @click="$router.push('/foo/2')">動態路徑轉屬性</button> <br>
    <button @click="$router.push({name: 'Foobar', params:{nickname: 'mengday', status: 1}})">params轉屬性</button> <br>
    <button @click="$router.push({path: '/bar/666', query:{username: 'mengday', age: 2}})">query轉屬性</button> <br>
    <router-view></router-view>
  </div>
</template>

<script>
  export default {
    name: 'App',
  }
</script>

Foo.vue

<template>
    <div>
      Foo <br>
      this.$route.params.id={{ this.$route.params.id }}<br>
      {id} = {{id}}
    </div>
</template>

<script>
  export default {
    name: 'Foo',
    props: ['id']
  }
</script>

Bar.vue

<template>
    <div>
      Bar {{ this.$route.params.id }} <br>
      {id} = {{id}} <br>
      {username} = {{username}} <br>
      {age} = {{age}} <br>
      {baz} = {{baz}} <br>
    </div>
</template>

<script>
  export default {
    name: 'Bar',
    props: ['id', 'username', 'age', 'baz']
  }
</script>

Foobar.vue

<template>
    <div>
      Foobar <br>
      {nickname} = {{ nickname }} <br>
      {status} = {{ status }} <br>
    </div>
</template>

<script>
  export default {
    name: 'Foobar',
    props: ['nickname', 'status']
  }
</script>

src/router/index.js

import Vue from 'vue'
import Router from 'vue-router'

import Foo from '../components/Foo'
import Bar from '../components/Bar'
import Foobar from '../components/Foobar'

Vue.use(Router)

export default new Router({
  routes: [
    {
      path: '/foo/:id',
      component: Foo,
      props: true
    },
    {
      path: '/bar/:id',
      component: Bar,
      props: (route) => ({
        id: route.params.id,
        username: route.query.username,
        age: route.query.age,
        baz: 'baz'
      })
    },
    {
      path: '/foobar',
      name: 'Foobar',
      component: Foobar,
      props: (route) => ({
        nickname: route.params.nickname,
        status: route.params.status
      })
    }
  ]
})

七、重定向與別名

重定向”的意思是,當用戶訪問 /a時,URL 將會被替換成 /b,然後匹配路由爲 /b。
別名:就是爲一個組件的path另起一個別名,path和alias訪問任意一個路徑都能路由到對應的組件。

src/router/index.js

import Vue from 'vue'
import Router from 'vue-router'

import Foo from '../components/Foo'
import Bar from '../components/Bar'
import Foo2 from '../components/Foo2'

Vue.use(Router)

export default new Router({
  routes: [
    {
      path: '/index',
      redirect: '/foo'
    },
    {
      path: '/index2',
      redirect: {name: 'Bar'}
    },
    {
      path: '/foo',
      component: Foo
    },
    {
      path: '/bar',
      name: 'Bar',
      component: Bar
    },
    {
      path: '/foo2',
      alias: '/foo22',
      component: Foo2
    }
  ]
})

App.vue

<template>
  <div id="app">
    <button @click="$router.push('/index')">redirect: '/foo'</button> <br>
    <button @click="$router.push('/index2')">redirect: {name: Bar}</button> <br>
    <button @click="$router.push('/foo2')"> foo2 </button> <br>
    <button @click="$router.push('/foo22')"> alias </button> <br>
    <router-view></router-view>
  </div>
</template>

<script>
  export default {
    name: 'App'
  }
</script>

八、組件嵌套

一個單頁面應用是一個根組件(App.vue),根組件中會嵌套多個子組件,子組件中又會嵌套多個孫子組件。總之一個單頁面應用是由無數個子組件嵌套而成,就像一棵倒立的樹結構一樣。

在上一個示例的基礎上,寫一個嵌套結構的組件。
Foo1.vue

<template>
    <div>
      Foo1
    </div>
</template>

<script>
  export default {
    name: 'Foo1'
  }
</script>

<style scoped>

</style>

Foo2.vue

<template>
    <div>
      Foo2
    </div>
</template>

<script>
  export default {
    name: 'Foo2'
  }
</script>

<style scoped>

</style>

src/router/index.js
組件可以通過children屬性來配置子組件。

import Vue from 'vue'
import Router from 'vue-router'

import Foo from '../components/Foo'
import Bar from '../components/Bar'
import Foo1 from '../components/Foo1'
import Foo2 from '../components/Foo2'

Vue.use(Router)

export default new Router({
  routes: [
    {
      path: '/foo',
      component: Foo,
      children: [
        {
          path: 'foo1',
          component: Foo1
        },
        {
          path: 'foo2',
          component: Foo2
        }
      ]
    },
    {
      path: '/bar/:id',
      component: Bar
    }
  ]
})

Foo.vue

<template>
    <div>
      Foo
      <p>
        <router-link to="/foo/foo1">Go to Foo1</router-link>
        <router-link to="/foo/foo2">Go to Foo2</router-link>
      </p>
      <router-view></router-view>
    </div>
</template>

<script>
  export default {
    name: 'Foo'
  }
</script>

<style scoped>

</style>

在這裏插入圖片描述

九、命名視圖

命名視圖就是給<router-link>設置一個name屬性,name屬性的值就是在配置路由時指定的name值,設置了name意思就是該視圖只用於展示name對應的組件內容,而不會展示別的組件的內容。

當在同級展示多個視圖(< router-view >),而不是嵌套裏面。一個視圖(< router-view >)對應一個組件(component), 多個視圖就對應多個組件。在配置路由時使用components來配置多個組件,同時給每個組件起一個名稱。在使用視圖時通過名稱來指定該視圖對應的組件。

Top.vue

<template>
    <div>
      Top
    </div>
</template>

<script>
  export default {
    name: 'Top'
  }
</script>

<style scoped>

</style>

Left.vue

<template>
    <div>
      Left
    </div>
</template>

<script>
  export default {
    name: 'Left'
  }
</script>

<style scoped>

</style>

Main.vue

<template>
    <div>
      Main
    </div>
</template>

<script>
  export default {
    name: 'Main'
  }
</script>

<style scoped>

</style>

src/router/index.js

import Vue from 'vue'
import Router from 'vue-router'

import Top from '../components/Top'
import Left from '../components/Left'
import Main from '../components/Main'

Vue.use(Router)

export default new Router({
  routes: [
    {
      path: '/',
      components: {
        top: Top,
        left: Left,
        main: Main
      }
    }
  ]
})

App.vue

<template>
  <div id="app">
    <router-view class="top" name="top"></router-view>
    <router-view class="left" name="left"></router-view>
    <router-view class="main" name="main"></router-view>
  </div>
</template>

<script>
  export default {
    name: 'App'
  }
</script>

<style>
  .top {
    float: left;
    width: 100%;
    height: 100px;
    background-color: orange;
  }
  .left {
    float: left;
    width: 25%;
    height: 700px;
    background-color: #2c3e50;
  }
  .main {
    float: left;
    width: 75%;
    height: 700px;
    background-color: dimgray;
  }
</style>

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章